CHỈNH SỬA: Xem thêm this more elegant answer.
Dưới cơ chế dựa trên một C preprocessor macro mà tôi đã thực hiện thành công trong một lớp JNI.
Macro trên CATCH_CPP_EXCEPTION_AND_THROW_JAVA_EXCEPTION
chuyển đổi ngoại lệ C++ thành ngoại lệ Java.
Thay thế mypackage::Exception
bằng ngoại lệ C++ của riêng bạn. Nếu bạn chưa xác định my.group.mypackage.Exception
tương ứng trong Java, hãy thay thế "my/group/mypackage/Exception"
theo "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"); \
}
File Java_my_group_mypackage_example.cpp
sử dụng macro trên:
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
}
Chỉ cần cung cấp thông tin hoặc sự tò mò, tôi cung cấp dưới đây mã Java tương ứng (file example.java
). Lưu ý rằng "my-DLL-name
" là mã C/C++ ở trên được biên dịch dưới dạng DLL ("my-DLL-name
" không có phần mở rộng ".dll
"). Điều này cũng hoạt động hoàn hảo bằng cách sử dụng thư viện chia sẻ 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
}
}
Thứ nhất, tạo example.class
từ example.java
(sử dụng javac
hoặc yêu thích IDE hoặc maven của bạn ...). Thứ hai, tạo tập tin tiêu đề C/C++ Java_my_group_mypackage_example.h
từ example.class
sử dụng javah
.
Kiểm tra đơn vị, nhật ký ... Các lựa chọn thay thế duy nhất tôi biết (nhưng tôi biết faaar từ mọi thứ, vì vậy hãy xem thêm :)) – Warpzit
Bạn có kiểm soát được mã gốc không? Hoặc chỉ là phía Java? –
Chỉ có lớp mã gốc hàng đầu, tức là lớp JNI Binder. – Graeme