編輯: 另請參見this more elegant answer。
下面機制是基於一個C preprocessor macro,我已經成功一個JNI層內實現。
上述宏CATCH_CPP_EXCEPTION_AND_THROW_JAVA_EXCEPTION
將C++異常轉換爲Java異常。
用您自己的C++異常替換mypackage::Exception
。如果您還沒有在Java中定義相應的my.group.mypackage.Exception
,則將"my/group/mypackage/Exception"
替換爲"java/lang/RuntimeException"
。
#define CATCH_CPP_EXCEPTION_AND_THROW_JAVA_EXCEPTION \
\
catch (const mypackage::Exception& e) \
{ \
jclass jc = env->FindClass("my/group/mypackage/Exception"); \
if(jc) env->ThrowNew (jc, e.what()); \
/* if null => NoClassDefFoundError already thrown */ \
} \
catch (const std::bad_alloc& e) \
{ \
/* OOM exception */ \
jclass jc = env->FindClass("java/lang/OutOfMemoryError"); \
if(jc) env->ThrowNew (jc, e.what()); \
} \
catch (const std::ios_base::failure& e) \
{ \
/* IO exception */ \
jclass jc = env->FindClass("java/io/IOException"); \
if(jc) env->ThrowNew (jc, e.what()); \
} \
catch (const std::exception& e) \
{ \
/* unknown exception */ \
jclass jc = env->FindClass("java/lang/Error"); \
if(jc) env->ThrowNew (jc, e.what()); \
} \
catch (...) \
{ \
/* Oops I missed identifying this exception! */ \
jclass jc = env->FindClass("java/lang/Error"); \
if(jc) env->ThrowNew (jc, "unidentified exception"); \
}
使用上述宏文件Java_my_group_mypackage_example.cpp
:
JNIEXPORT jlong JNICALL Java_my_group_mypackage_example_function1
(JNIEnv *env, jobject object, jlong value)
{
try
{
/* ... my processing ... */
return jlong(result);
}
CATCH_CPP_EXCEPTION_AND_THROW_JAVA_EXCEPTION
return 0;
}
JNIEXPORT jstring JNICALL Java_my_group_mypackage_example_function2
(JNIEnv *env, jobject object, jlong value)
{
try
{
/* ... my processing ... */
jstring jstr = env->NewStringUTF("my result");
return jstr;
}
CATCH_CPP_EXCEPTION_AND_THROW_JAVA_EXCEPTION
return 0;
}
JNIEXPORT void JNICALL Java_my_group_mypackage_example_function3
(JNIEnv *env, jobject object, jlong value)
{
try
{
/* ... my processing ... */
}
CATCH_CPP_EXCEPTION_AND_THROW_JAVA_EXCEPTION
}
只爲信息或好奇,我提供相應的Java代碼下面(文件example.java
)。請注意,「my-DLL-name
」是上述編譯爲DLL的C/C++代碼(「my-DLL-name
」,沒有「.dll
」擴展名)。這也適用於使用Linux/Unix共享庫*.so
。
package my.group.mypackage;
public class Example {
static {
System.loadLibrary("my-DLL-name");
}
public Example() {
/* ... */
}
private native int function1(int); //declare DLL functions
private native String function2(int); //using the keyword
private native void function3(int); //'native'
public void dosomething(int value) {
int result = function1(value);
String str = function2(value); //call your DLL functions
function3(value); //as any other java function
}
}
首先,生成example.class
從example.java
(使用javac
或者你喜歡的IDE或Maven ...)。其次,使用javah
從example.class
生成C/C++頭文件Java_my_group_mypackage_example.h
。
單元測試,日誌...我知道的唯一選擇(但我知道所有東西都是faaar,所以請進一步看:)) – Warpzit
您是否控制了本機代碼?或者只是Java方面? –
只有本地代碼的最頂層,即JNI活頁夾層。 – Graeme