JNI和C ++ - UnsatisfiedLinkError

时间:2014-01-15 09:36:48

标签: java c++ java-native-interface

我正在使用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;

有什么想法吗?

3 个答案:

答案 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++?