Sende C ++ – String nach Java über JNI

Ich arbeite an der C ++ – Seite eines Projekts, das eine Android-Anwendung erstellt. Es gibt einige Informationen (über Strings und String Arrays), die ich an die Java Applikation (via JNI) übergeben muss. Ich habe das noch nie gemacht, und die Leute, die in umgekehrter Richtung arbeiten, haben keine Erfahrung mit C ++ und geben zu, dass sie nicht wirklich helfen können.

Ich habe den folgenden Code gefunden (von hier )

  • Kann ein GridView eine Fußzeile und Header wie ListView haben?
  • Wie fülle man die leeren Räume mit Inhalt unter dem Bild in android
  • Google Vision API Samples: Holen Sie sich die CameraSource zum Fokus
  • Dateifreigabe zwischen Android-Telefon und PC
  • Bestätigen Sie, ob andre asset Eintrag eine Datei oder ein Verzeichnis ist
  • Wie mache ich ein scrollbares TableLayout?
  • #include <jni.h> #include "ArrayHandler.h" JNIEXPORT jobjectArray JNICALL Java_ArrayHandler_returnArray (JNIEnv *env, jobject jobj){ jobjectArray ret; int i; char *message[5]= {"first","second","third","fourth","fifth"}; ret= (jobjectArray)env->NewObjectArray(5,env->FindClass("java/lang/String"),env->NewStringUTF("")); for(i=0;i<5;i++) { env->SetObjectArrayElement(ret,i,env->NewStringUTF(message[i])); } return(ret); } 

    Aber das macht keinen Sinn für mich. Meistens bin ich mir nicht sicher, wie ich das in die C ++ – Seite des Programms integrieren soll und ich verstehe nicht genau, wie das funktioniert. Ist der Code, der die Nachricht bei Ausführung der return(ret); aussendet return(ret); Linie? Oder während der Ausführung der Zeile innerhalb der Schleife?

    Im Idealfall möchte ich, dass das String / String-Array "live" in Zeile und nicht am Ende einer Funktion ausgesendet wird, so dass ich keine neue Funktion übernehmen muss.

    Wird der Code, den ich gefunden habe, was ich will (mit etwas Adaption)? Ist das, was ich suche, auch möglich? Wenn ja, wie kann ich das machen?

    EDIT / UPDATE: Nachdem ich den Tag damit verbracht habe, JNI und die Terminologie zu betrachten, glaube ich, dass ich es versäumt habe, richtig zu kommunizieren, was ich schaue, um hier zu erreichen und als Kommentar zu @ jogabonitos Antwort / Antwort.

    Das heißt gesagt Der Code, an dem ich arbeite, ist für einen IM-Client, der Meldung und Präsenz-Updates auf die Android-Java-Anwendung (über JNI) drücken muss, damit die Android-Anwendung nicht für Updates abfragt. Ich habe es gelernt zu lernen, wie man die Funktionen für den Java-Code einrichtet, um auf weitere Informationen zu rufen. Allerdings habe ich keine Ahnung, wie man neue Nachricht oder Präsenz Informationen (jabber Stanza Strings) auf den Java-Code, wenn es kommt in Puls. Alle Code, den ich gesehen habe, wie dies zu tun (siehe unten zum Beispiel) scheint zu sein Erfordern Informationen aus dem Java-Code (env, class, methodid, etc).

    Es macht keinen Sinn für mich, wie das sein soll, wenn es nicht der Java-Code ist, der die Funktion aufruft, aber mein C ++ – Code. Jede Erklärung / Hilfe wäre sehr geschätzt.

     #include <string.h> #include <stdio.h> #include <jni.h> jstring Java_the_package_MainActivity_getJniString( JNIEnv* env, jobject obj){ jstring jstr = (*env)->NewStringUTF(env, "This comes from jni."); jclass clazz = (*env)->FindClass(env, "com/inceptix/android/t3d/MainActivity"); jmethodID messageMe = (*env)->GetMethodID(env, clazz, "messageMe", "(Ljava/lang/String;)Ljava/lang/String;"); jobject result = (*env)->CallObjectMethod(env, obj, messageMe, jstr); const char* str = (*env)->GetStringUTFChars(env,(jstring) result, NULL); // should be released but what a heck, it's a tutorial :) printf("%s\n", str); return (*env)->NewStringUTF(env, str); } 

  • SecurityException: Permission denied (fehlende INTERNET-Berechtigung?)
  • Live-Stream-Video von einem Android-Handy zu einem anderen über WiFi
  • Wie kann ich Type_orientation (is deprecated) für Android 4.0.3 ersetzen?
  • Transfer von InputStream zu einem anderen Service (über Prozessgrenzen hinweg) mit ParcelFileDescriptor.createPipe () schlägt mit "EBADF (schlechte Dateinummer)"
  • Android-Zeichen durch Zeichen Anzeige Text Animation
  • Ende des eingehenden Anrufs programmgesteuert
  • 4 Solutions collect form web for “Sende C ++ – String nach Java über JNI”

    In der Funktion, die Sie geteilt haben, erstellen Sie in Ihrem C ++ – Code ein Objekt-Array mit NewObjectArray . Dann erstellen Sie in Ihrer for-Schleife einen String mit NewStringUTF und speichern ihn mit einem Index in Ihrem Array mit SetObjectArrayElement . Bisher ist Ihr Objekt-Array nur Ihrem C ++ – Code und nicht Ihrem Java-Code bekannt. Nur wenn du zurückkommst, wird dein Java-App Zugang dazu bekommen.
    Ich kann an ein paar Möglichkeiten denken, die Zeichenfolge aus dem C ++ zu schicken, obwohl es nicht genau das ist, was du beabsichtigt hast.

    1. Übergeben Sie ein String-Array an Ihre native Funktion. In nativem Code kannst du mit GetObjectArrayElement auf jedes Element GetObjectArrayElement und es mit SetObjectArrayElement . Das wird wohl sinnlos sein, da du am Ende eine Funktion aufrufen musst, die ich dir nicht verlange.

    2. Wenn Sie bereits eine Zeichenfolge haben, die als Feld in Ihrem Java-Code definiert ist, erhalten Sie von Ihrem Eingeborenen Zugriff auf es mit GetFieldID und GetObjectField , und Sie können es mit SetObjectField . Ich weiß nicht, wie Sie Ihren Java-Code signalisieren, dass das Feld aktualisiert wurde (wenn Sie es brauchen)

    BEARBEITEN
    Die aktualisierte Funktion, die Sie geschrieben haben, soll aus der Java-Ebene aufgerufen werden. Der Hinweis hierfür ist der Name der Funktion Java_the_package_MainActivity_getJniString . Um Java-Code aus einem nativen Kontext aufzurufen, benötigen Sie Hinweise auf die env und obj von Java. Schau mal an Wie lade ich meine eigene Java-Klasse in C auf Android? Für eine Annäherung, zum dieses zu erhalten Sie müssen wahrscheinlich auch nachschlagen, wie man globale Referenzen in JNI verwendet

    Auf Anfrage von @Sam ist hier eine Methode, die die Verwendung von modifiziertem UTF-8 vermeidet, weil wir nicht wissen, dass es sicher ist, dies zu tun.

    NewStringUTF erstellt einen String aus seiner modifizierten UTF-8-Codierung. Es ist nicht richtig, es mit Benutzerdaten zu verwenden – es ist unwahrscheinlich, dass es mit modifiziertem UTF-8 codiert wird. Wir könnten nur hoffen, dass die Charaktere in den Daten beschränkt sind, um es kompatibel zu halten. Stattdessen können wir es richtig umwandeln.

    JNI verwendet modifizierte UTF-8-Strings während seiner API. Wir können Strings verwenden, die wir kennen, sind kompatibel, insbesondere Literale für Java Identifikatoren (außer nicht alle Währungssymbole).

    Im Folgenden sind zwei native Methodenimplementierungen. Die zweite ist in den meisten Fällen besser.

    Für diese native Methode:

     private static native String getJniString(); 

    Hier ist eine Implementierung:

     JNIEXPORT jstring JNICALL Java_the_Package_MainActivity_getJniString(JNIEnv *env, jclass) { std::string message = "Would you prefer €20 once " "or ₹10 every day for a year?"; int byteCount = message.length(); jbyte* pNativeMessage = reinterpret_cast<const jbyte*>(message.c_str()); jbyteArray bytes = env->NewByteArray(byteCount); env->SetByteArrayRegion(bytes, 0, byteCount, pNativeMessage); // find the Charset.forName method: // javap -s java.nio.charset.Charset | egrep -A2 "forName" jclass charsetClass = env->FindClass("java/nio/charset/Charset"); jmethodID forName = env->GetStaticMethodID( charsetClass, "forName", "(Ljava/lang/String;)Ljava/nio/charset/Charset;"); jstring utf8 = env->NewStringUTF("UTF-8"); jobject charset = env->CallStaticObjectMethod(charsetClass, forName, utf8); // find a String constructor that takes a Charset: // javap -s java.lang.String | egrep -A2 "String\(.*charset" jclass stringClass = env->FindClass("java/lang/String"); jmethodID ctor = env->GetMethodID( stringClass, "<init>", "([BLjava/nio/charset/Charset;)V"); jstring jMessage = reinterpret_cast<jstring>( env->NewObject(stringClass, ctor, bytes, charset)); return jMessage; } 

    JNI ist umständlich. Wenn wir also das Wissen verschieben können, dass der native String "UTF-8" zur Java-Seite ist, können wir dies tun:

     private static String getJniString2() { return new String(getJniStringBytes(), Charset.forName("UTF-8")); } private static native byte[] getJniStringBytes(); 

    Und die viel einfachere Umsetzung:

     JNIEXPORT jbyteArray JNICALL Java_the_Package_MainActivity_getJniStringBytes(JNIEnv *env, jclass) { std::string message = "Would you prefer €20 once " "or ₹10 every day for a year?"; int byteCount = message.length(); jbyte* pNativeMessage = reinterpret_cast<const jbyte*>(message.c_str()); jbyteArray bytes = env->NewByteArray(byteCount); env->SetByteArrayRegion(bytes, 0, byteCount, pNativeMessage); return bytes; } 

    In der Regel mit JNI gehen die Anrufe von der JVM in den C-Code. Das normale Paradigma wäre:

    1. Java-Programmierer machen eine Java- class mit mehreren Methoden als native deklariert (keine Implementierung)
    2. Java-Programmierer kompilieren die class mit javac
    3. Java-Programmierer laufen javah gegen die kompilierte .class Datei, dies erzeugt eine .h Header-Datei
    4. C-Programmierer #include die neue Header-Datei und implementiere die Schnittstelle

    Die einzigen Beispiele, die ich gesehen habe, dies in umgekehrter Richtung zu tun (C-Code, der Kontakt mit Java initiiert) beinhaltet, dass der C-Code tatsächlich eine JVM erstellt.

    Um Ihre Frage über das Codebeispiel zu beantworten, werden die erzeugten Java Strings mit der return-Anweisung am Ende der Codeausführung zurückgegeben. Logisch ist dies, wenn der Programmablauf für diesen Thread der Ausführung an die JVM zurückgegeben wird.

    Sie können eine C-String in einen Jstring umwandeln und zurückgeben. Ein Beispiel würde etwas aussehen:

     JNIEXPORT jstring JNICALL Java_Class_Method(jstring data) { // jstring to char * const char *cStr = (*env)->GetStringUTFChars(env, data, NULL); // convert char * to jstring and return it return ((*env)->NewStringUTF(env, cStr)); } 
    Das Android ist ein Google Android Fan-Website, Alles ├╝ber Android Phones, Android Wear, Android Dev und Android Spiele Apps und so weiter.