2016-07-26 13 views
2

Ich möchte eine C++ Map nach Java übertragen und habe keine Ahnung, wie man den Rückgabeparameter definiert, damit die Methode funktioniert. Ich hatte keine Probleme mit String oder Int als Return-Parameter, aber ich kann nicht funktionieren.
Meine Java-Methode wie folgt aussieht:Convert C++ Map zu Jobject JNI?

private native Map<String,String> sayHello(); 

Meine C++ Code ist:

#include <stdio.h> 
#include "stdafx.h" 
#include "jni.h" 
#include "HelloJNI.h" 
#include <utility> 
#include <map> 
#include <string.h> 
#include <iostream> 

using namespace std; 

JNIEXPORT jobject JNICALL Java_HelloJNI_sayHello 
(JNIEnv *, jobject) 
{ 
    map<string, string> mMap; 
    mMap["1"] = "Ladi"; 
    mMap["2"] = "Dida"; 
    return mMap; 
} 

Und natürlich ich einen Fehler, mir zu sagen, ich MMAP konvertieren müssen irgendwie jobject. Aber ich habe keine Ahnung, wie ich das machen soll.

Ich hoffe, es ist kein Doppel-Post, ich habe nur einige Fragen über die Übertragung von Listen.

Vielen Dank im Voraus.

+0

Ein unabhängiges Problem, aber eine, die in jeder Implementierung Ihrer Methode wäre, ist, welche Zeichencodierung die Zeichenfolgen in "mMap" verwenden. Code, der '.c_str()' verwendet, setzt voraus, dass die Daten keine NUL-Zeichen enthalten. Und Code, der 'NewStringUTF' verwendet, geht davon aus, dass die Codierung (oder zumindest so weit wie die erwarteten Daten gehen) als _modified_ UTF-8 interpretiert werden kann. –

Antwort

4

Sie müssen jni api verwenden, um HashMap Java-Klasse zu finden, dann seine Methoden für die Konstruktion und Einfügen von Elementen. Fügen Sie dann alle Elemente hinzu und geben Sie diese Karte schließlich zurück. Es sollte wie folgt aussehen (Warnung - Pseudocode !!!)

env->PushLocalFrame(256); // fix for local references 

jclass hashMapClass= env->FindClass(env, "java/util/HashMap"); 
jmethodID hashMapInit = env->GetMethodID(env, hashMapClass, "<init>", "(I)V"); 
jobject hashMapObj = env->NewObject(env, hashMapClass, hashMapInit, mMap.size()); 
jmethodID hashMapOut = env->GetMethodID(env, hashMapClass, "put", 
      "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); 

for (auto it : mMap) 
{ 
    env->CallObjectMethod(env, hashMap, put, 
     env->NewStringUTF(it->first.c_str()), 
     env->NewStringUTF(it->second.c_str())); 
} 

env->PopLocalFrame(hashMap); 

return hashMap; 

ps. Ich Code normalerweise jni unter Android, aber oben Code sollte das gleiche unter anderen Plattformen funktionieren.

+3

Schön. Aber ich denke, es wäre einfacher, einfach ein leeres 'HashMap'-Objekt an den nativen Code zu übergeben und die' put'-Methode aufzurufen, wie 'private native void sayHello (Map jmap);' –

+0

@ mrtnj danke für deine schnelle Antwort. Ich werde es heute versuchen und lassen Sie wissen, ob ich es in Gang bringen könnte :) AndrewHenle das ist eine nette Idee, und ich denke, es wäre definitiv einfacher als die andere Lösung, aber das Problem ist in meinem Programm die Karte sein muss gefüllt mit Werten, bevor die native Java-Funktion aufgerufen wird. Aber trotzdem danke Kumpel! –

+0

@AndrewHenle Ja. Es ist oft weniger fehleranfällig, einige JNI-Daten zurück nach Java zu verschieben. 'private native' Methoden sind der Weg zu gehen. 'public'-Methoden sollten jedoch eine natürliche Java-Schnittstelle haben. –