Anzeige:
Ergebnis 1 bis 2 von 2

Thema: JNI: Mehrere Argmuente

  1. #1
    Registrierter Benutzer
    Registriert seit
    14.01.2004
    Beiträge
    27

    JNI: Mehrere Argmuente

    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
    Code:
    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
    Code:
    #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.dll");
    	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

  2. #2
    Registrierter Benutzer
    Registriert seit
    14.01.2004
    Beiträge
    27
    Ok, habs nun zum laufen gebracht

    Mit der gleichen Java-Klasse und folgendem CPP-Code:
    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.

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •