2014-01-15 5 views
3

Я использую JNI для вызова некоторого кода на C, однако, когда я хочу перейти на C++, JNI бросает UnsatisfiedLinkError всякий раз, когда я пытаюсь вызвать метод.JNI и C++ - 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++ терпит неудачу с:

Exception in thread "main" java.lang.UnsatisfiedLinkError: de.zdv.research.emdu.CI3CppEncryptionTools.encrypt(Ljava/lang/String;)Ljava/lang/String; 

Любые идеи?

ответ

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){ 
     //------------ 
} 
+0

Я уже пробовал это, и, к сожалению, это не сработало, поскольку я понял, что 'JNIEXPORT' и' JNICALL' являются макросами для обеспечения правильной привязки C ... но я видел примеры, где они были опущены, и это сработало. – yvesonline

+3

@yvesonline JNIEXPORT не проблема, проблема в том, что ваши аргументы реализации не совпадают с вашим определением. Второй аргумент должен быть jclass, а не заданием, чтобы соответствовать определению JNI статической функции. – Samhain

+0

Ах! Извините, я этого не видел! Это было именно то, что было неправильно. Благодаря! Интересно, почему версия C работала таким образом ... – yvesonline

0

Убедитесь, что java может найти вашу динамическую родную библиотеку в том же каталоге, где вы запускаете JVM. Проверьте также, что ваша динамическая библиотека скомпилирована для той же архитектуры, что и JVM, с которой вы запускаете свою программу (например, 32-разрядная версия для 32-разрядного JMV или 64 для 64-разрядной JVM)

+0

Звоню Java приложения с помощью 'Java -Djava.library.path = Lib ...', чтобы убедиться, что библиотека находится. Архитектура соответствует, как я уже упоминал, версия C работает без проблем. – yvesonline

0

При компиляции C++, вы должны иметь extern "C" префикс перед функциями деклараций/определений.

Но есть и другие различия, см JNI Calls different in C vs C++?

Смежные вопросы