Anmelden

Archiv verlassen und diese Seite im Standarddesign anzeigen : JNI: Mehrere Argmuente



McHurt
25-04-2006, 09:11
Hallo zusammen,
Ich spiele gerade ein wenig mit JNI herum, konkret rufe ich aus C++-Code eine Java-Methode auf. Dazu hab ich ein wenig Code aus verschiedenen Quellen gesammelt, da das ganze sehr schlecht dokumentiert ist (oder hab ich die guten Dokus einfach nicht gefunden?).
Soweit so gut, ich kann der Methode auch einen Int übergeben, nur bleiben 2 Probleme:
1. Ich kann keine Strings übergeben
2. Ich kann nicht mehrere Argumente übergeben

Beides endet mit einem Nullpointer. Wie folgt mein Code:

Java


public class Test{
public static void main(int[] args){

}

static void printSomething(String str1){
System.out.println("Hello Java!");
//System.out.println("Int in java: "+i);
//System.out.println("Int in java: "+j);
System.out.println("String1: "+str1);
//System.out.println("String2: "+str2);
}
}

CPP


#include <jni.h>
#include <iostream>
#include <windows.h>

using namespace std;

typedef jint (*JNI_CREATEJAVAVM)(JavaVM **pvm, void ** penv, void *args);
int main()
{
JavaVM *jvm;
JavaVMInitArgs vm_args;
JavaVMOption options[2];
jint ret = -1;
HMODULE hLib;
JNI_CREATEJAVAVM JNI_CreateJavaVM = NULL;
JNIEnv *env;
jstring jstr1;
jstring jstr2;
jint jinteger;
jobjectArray args;

hLib = LoadLibrary("C:\\Program Files\\Java\\jdk1.5.0_06\\jre\\bin\\client\\jvm.dl l");
if(hLib == NULL)
{
cout<<"shit happens";
return FALSE;
}
options[0].optionString = "-Djava.compiler=NONE";
options[1].optionString = "-Djava.class.path=.";

vm_args.version = JNI_VERSION_1_4;
vm_args.options = options;
vm_args.nOptions = 2;
vm_args.ignoreUnrecognized = JNI_FALSE;


JNI_CreateJavaVM = (JNI_CREATEJAVAVM) GetProcAddress(hLib, "JNI_CreateJavaVM");

if(JNI_CreateJavaVM != NULL)
{
ret = (*JNI_CreateJavaVM)(&jvm,(void**)&env,&vm_args);
if(ret<0)
{
cout << ret << endl;
cout<<"Sorry,JVM is not set up!\n";
}
else
{
cout<<"Hello,JVM\n";
}
}else{
// Can't Get JNI_CreatJavaVM address
return 0;
}

jstr1 = env->NewStringUTF("String1");
jstr2 = env->NewStringUTF("String2");
jinteger = 100;

//args = env->NewObjectArray(1, env->FindClass("java/lang/String"), jstr1);

jclass cls = env->FindClass("Test");
jmethodID mid = env->GetStaticMethodID(cls, "printSomething", "(java/lang/String)V");
cout << "check1" << endl;
env->CallStaticVoidMethod(cls, mid, jstr1); // Hier findet der Nullpointer statt

jvm->DestroyJavaVM();
}


Wie ihr seht, benutze ich Windows als Entwicklungsclient, jedoch sollte der CPP-Code sowohl auf UNIX wie auf Windows kompilieren. Die Einbindung von windows.h erschien bislang als einzige Variante zu laufen.
Wenn jemand also auch gerade wüsste, wie ich das ganze ohne plattformspezifischen Code zum laufen bringe, wäre ich auch sehr dankbar.

Gruss

McHurt
26-04-2006, 14:25
Ok, habs nun zum laufen gebracht :)

Mit der gleichen Java-Klasse und folgendem CPP-Code:


#include <jni.h>
#include <iostream>

using namespace std;

int main()
{
JavaVM* jvm;
JNIEnv* env;
JavaVMInitArgs vm_args;
JavaVMOption options[2];
long status;

jclass class_Test;
jclass class_String;
jobjectArray args;
jmethodID id_main;

jstring jstr;
jstring jstr2;

options[0].optionString = "-Djava.compiler=NONE";
options[1].optionString = "-Djava.class.path=.";

vm_args.version = JNI_VERSION_1_4;
vm_args.nOptions = 2;
vm_args.options = options;
vm_args.ignoreUnrecognized = false;

status = JNI_CreateJavaVM(&jvm, (void**) &env, &vm_args);
if (status == JNI_ERR)
{
cout << "Failed creating JVM: " << status << endl;
return 1;
}else
{
cout << "JVM created" << endl;
}

class_Test = env->FindClass("Test");
id_main = env->GetStaticMethodID(class_Test, "printSomething", "(IILjava/lang/String;Ljava/lang/String;)V");

jstr = env->NewStringUTF("testtest");
jstr2 = env->NewStringUTF("testtest2");

env->CallStaticVoidMethod(class_Test, id_main, 100, 200, jstr, jstr2);
jvm->DestroyJavaVM();

return 0;
}



Das trickreiche daran ist, dass man wenn man GCC unter Windows verwendet, die eine Bibliothek "jvm.lib" mit dem Tool reimp.exe in eine *.a Datei umwandeln muss, sonst scheint der GCC Probleme zu bekommen.