我正在使用JNI成功调用一些C代码,但是当我想要更改为C ++时,每当我尝试调用方法时,JNI都会抛出UnsatisfiedLinkError
。
这个有效:
g++ -c -Icryptopp562 -O3 -fPIC -fpermissive CI3CppEncryptionToolsImpl.cpp
gcc -I${JAVA_HOME}/include -O3 -shared -fPIC -o libCI3CppEncryptionTools.so de_zdv_research_emdu_CI3CppEncryptionTools.c CI3CppEncryptionToolsImpl.o -lcryptopp
有了这个,我得到一个UnsatisfiedLinkError
:
g++ -c -Icryptopp562 -O3 -fPIC -fpermissive CI3CppEncryptionToolsImpl.cpp
g++ -I${JAVA_HOME}/include -O3 -shared -fPIC -fpermissive -o libCI3CppEncryptionTools.so de_zdv_research_emdu_CI3CppEncryptionTools.cpp CI3CppEncryptionToolsImpl.o -lcryptopp
生成的标题如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class de_zdv_research_emdu_CI3CppEncryptionTools */
#ifndef _Included_de_zdv_research_emdu_CI3CppEncryptionTools
#define _Included_de_zdv_research_emdu_CI3CppEncryptionTools
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: de_zdv_research_emdu_CI3CppEncryptionTools
* Method: encrypt
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_de_zdv_research_emdu_CI3CppEncryptionTools_encrypt
(JNIEnv *, jclass, jstring);
/*
* Class: de_zdv_research_emdu_CI3CppEncryptionTools
* Method: decrypt
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_de_zdv_research_emdu_CI3CppEncryptionTools_decrypt
(JNIEnv *, jclass, jstring);
#ifdef __cplusplus
}
#endif
#endif
我的实现(.cpp)如下,我省略了decrypt
方法:
#include <jni.h>
#include "CI3CppEncryptionToolsImpl.h"
#include "de_zdv_research_emdu_CI3CppEncryptionTools.h"
jstring
Java_de_zdv_research_emdu_CI3CppEncryptionTools_encrypt(JNIEnv *env, jobject obj, jstring s) {
return env->NewStringUTF(encrypt(env->GetStringUTFChars(s, JNI_FALSE)));
}
对于C版本,我只需改为编写return (*env)->NewStringUTF(env, encrypt((*env)->GetStringUTFChars(env, s, JNI_FALSE)));
。
C版本有效,C ++版本失败:
Exception in thread "main" java.lang.UnsatisfiedLinkError: de.zdv.research.emdu.CI3CppEncryptionTools.encrypt(Ljava/lang/String;)Ljava/lang/String;
有什么想法吗?
答案 0 :(得分:4)
在实现(.cpp)中,您已将函数编写为
jstring Java_de_zdv_research_emdu_CI3CppEncryptionTools_encrypt(JNIEnv *env, jobject obj, jstring s){
//---------
}
请将其写为
JNIEXPORT jstring JNICALL Java_de_zdv_research_emdu_CI3CppEncryptionTools_encrypt
(JNIEnv *, jclass, jstring){
//------------
}
答案 1 :(得分:0)
确保java可以在启动JVM的同一目录中找到动态本机库。还要检查您的动态库是否与您运行程序的JVM编译的架构相同(例如,对于32位JMV为32位,对于64位JVM为64位)
答案 2 :(得分:0)
如果编译C ++,则在函数声明/定义之前应该有一个extern "C"
前缀。
但还有其他差异,请参阅JNI Calls different in C vs C++?