2016-07-11 183 views
1

您好我目前正在開發一個項目,其中一個C++框架應該集成到一個Java程序中,因此我開始探索JNI。由於我是C++新手,目前我正在努力處理類型轉換以及應該在java本地方法中聲明哪些參數類型。Java JNI UnsatisfiedLinkError指向指針的C字符指針

在CPP文件我有以下方法:

using namespace std; 

int main(int argc,char**argv) 
{ 
    //do stuff 
} 

我相應的Java類看起來是這樣的:

public class JniTest { 

static { 
    System.loadLibrary("plain2snt"); 
} 

public JniTest() { 

    char[][] arguments = new char[][] {"resourceFile1.txt".toCharArray(), "resourceFile2.txt".toCharArray()}; 
    main(2, arguments); 
} 

public native int main(int argc, char[][] argv); 

} 

而對於Java類的頭文件如下:

#include <jni.h> 
/* Header for class testPackage_JniTest */ 

#ifndef _Included_testPackage_JniTest 
#define _Included_testPackage_JniTest 
#ifdef __cplusplus 
extern "C" { 
#endif 
/* 
* Class:  testPackage_JniTest 
* Method: main 
* Signature: (I[[C)I 
*/ 
JNIEXPORT jint JNICALL Java_testPackage_JniTest_main 
    (JNIEnv *, jobject, jint, jobjectArray); 

#ifdef __cplusplus 
} 
#endif 
#endif 

當我嘗試運行它時,出現以下錯誤:

Exception in thread "main" java.lang.UnsatisfiedLinkError: 
testPackage.JniTest.main(I[Ljava/lang/String;)I 
    at testPackage.JniTest.main(Native Method) 
    at testPackage.JniTest.<init>(JniTest.java:14) 
    at testPackage.Main.main(Main.java:6) 

我已經使用谷歌,JNI API參考等來查找Java和C++之間的類型匹配,但無法找到如何處理在Java中指針類型的字符指針。 argv參數的Java類中的實際類型定義與cpp框架中的char **匹配是什麼?

回答

0

當JVM嘗試調用本地方法時 - 它希望您已將它實現爲在javah生成的頭部指向的函數。即你的函數庫必須包含一個地址

JNIEXPORT jint JNICALL Java_testPackage_JniTest_main 
    (JNIEnv *, jobject, jint, jobjectArray) { 
    /* do stuff */ 
} 

並且捕獲的異常是一個聲明,表示本地方法沒有實現。

接下來,將arguments作爲字符數組的排列而不是String的數組更方便。

public JniTest() { 

    String[] arguments = new String[] {"resourceFile1.txt", "resourceFile2.txt"}; 
    main(2, arguments); 
} 

public native int main(int argc, String[] argv); 

} 

在C++中,你可以在明年獲得方式ARGS:

JNIEXPORT jint JNICALL Java_testPackage_JniTest_main (JNIEnv *, jobject thiz, jint argc, jobjectArray argv) { 
    for(jsize i = 0; i < env->GetArrayLength(argv); i++) { 
     jstring str = (jstring)env->GetObjectArrayElement(argv, i); 
     const char *c_str = env->GetStringUTFChars(str, NULL); 
     /* do whatever you want with c_str */ 
     env->ReleaseStringUTFChars(str, c_str); 
    } 

    /* ... */ 
} 
+0

謝謝您的回覆快!我將JNIEXPORT jint ...添加到我的庫中。至少這是我認爲我通過在cpp文件中實現此方法所做的(給出您提供的第三段代碼並對其進行調整)並將cpp文件重新編譯爲dll。這工作得很好,但我仍然得到了薩姆錯誤。是否有任何需要採取的步驟,或者我誤解了JNI API及其工作流程? – SvenBTU

+0

好的,我解決了這個問題。在我的Java類中,我沒有初始化該類的對象並調用本地主方法。所以我基本上只是將JniTest()更改爲public JniTest(){String [] arguments = new String [] {「resourceFile1.txt」,「resourceFile2.txt」}; JniTest test = new JniTest(); test.main(2,arguments); } – SvenBTU