2016-07-11 114 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