Mã của tôi bắt đầu bằng Java, gọi C++, sau đó gọi Java trở lại một lần nữa cho những thứ như tìm kiếm, nhận được, và thiết lập giá trị trường.
Trong trường hợp ai đó tìm kiếm một C++ cách tiếp cận tìm thấy trang này, tôi sẽ cày trên với điều này:
Những gì tôi đang bây giờ làm được gói cơ quan phương pháp JNI của tôi với một C++ try/catch block,
JNIEXPORT void JNICALL Java_com_pany_jni_JNIClass_something(JNIEnv* env, jobject self)
{
try
{
... do JNI stuff
// return something; if not void.
}
catch (PendingException e) // (Should be &e perhaps?)
{
/* any necessary clean-up */
}
}
nơi PendingException được khai báo trivially:
class PendingException {};
và tôi đang gọi phương thức sau đây sau khi gọi bất kỳ JNI từ C++, vì vậy nếu tình trạng Java ngoại lệ chỉ s lỗi, tôi sẽ giải cứu ngay lập tức và để cho các xử lý ngoại lệ Java bình thường thêm (phương pháp Native) dòng vào vết đống, trong khi cho C++ cơ hội để dọn dẹp trong khi tháo:
PendingException PENDING_JNI_EXCEPTION;
void throwIfPendingException(JNIEnv* env)
{
if (env->ExceptionCheck()) {
throw PENDING_JNI_EXCEPTION;
}
}
Java chồng của tôi dấu vết trông như thế này cho một env-> GetFieldId() gọi thất bại:
java.lang.NoSuchFieldError: no field with name='opaque' signature='J' in class Lcom/pany/jni/JniClass;
at com.pany.jni.JniClass.construct(Native Method)
at com.pany.jni.JniClass.doThing(JniClass.java:169)
at com.pany.jni.JniClass.access$1(JniClass.java:151)
at com.pany.jni.JniClass$2.onClick(JniClass.java:129)
at android.view.View.performClick(View.java:4084)
và khá tương tự nếu tôi gọi đến một phương pháp Java mà ném:
java.lang.RuntimeException: YouSuck
at com.pany.jni.JniClass.fail(JniClass.java:35)
at com.pany.jni.JniClass.getVersion(Native Method)
at com.pany.jni.JniClass.doThing(JniClass.java:172)
tôi không thể nói chuyện với gói ngoại lệ Java bên trong một ngoại lệ Java khác từ bên trong C++, mà tôi nghĩ là một phần của câu hỏi của bạn - tôi không thấy cần phải làm điều đó - nhưng nếu tôi làm, tôi sẽ làm điều đó với một trình bao bọc Java xung quanh phương pháp bản địa, hoặc chỉ mở rộng các phương thức ném ngoại lệ của tôi để lấy một jthrowable và thay thế env-> ThrowNew() gọi với một cái gì đó xấu xí: nó không may Sun đã không cung cấp một phiên bản của ThrowNew đã mất một jthrowable.
void impendNewJniException(JNIEnv* env, const char *classNameNotSignature, const char *message)
{
jclass jClass = env->FindClass(classNameNotSignature);
throwIfPendingException(env);
env->ThrowNew(jClass, message);
}
void throwNewJniException(JNIEnv* env, const char* classNameNotSignature, const char* message)
{
impendNewJniException(env, classNameNotSignature, message);
throwIfPendingException(env);
}
Tôi sẽ không xem xét tài liệu tham khảo bộ nhớ đệm (ngoại lệ) constructor lớp vì trường hợp ngoại lệ không được coi là một cơ chế kiểm soát dòng chảy thông thường, vì vậy không nên quan trọng nếu họ chậm. Tôi tưởng tượng nhìn lên không phải là chậm khủng khiếp anyway, kể từ khi Java có lẽ không bộ nhớ đệm của riêng mình cho rằng loại điều.
Bằng cách 'xử lý các trường hợp ngoại lệ' bạn có nghĩa là mã của bạn sẽ nhận thấy một ngoại lệ Java khi trở về từ Java đến C++, bọc nó trong một ngoại lệ khác và ném ngoại lệ mới này từ C++ lên Java? –