Это дополнение к ответу Эллиотта Хьюза . В моем ответе приведен пошаговый пример, объясняющий, как перехватывать исключения и как их переводить между словами C ++ и Java, используя слой JNI .
Краткий ответ
См. Правильный ответ Эллиота Хьюза .
Пример многократного использования
Этот ответ и фрагменты находятся в свободном доступе или в CC0 для упрощения повторного использования. Весь исходный код здесь обратно совместим с C ++ 03.
Чтобы использовать приведенный выше фрагмент, выполните следующие действия:
- Замените
mypackage::Exception
вашим собственным исключением C ++.
- Если соответствующее исключение Java
my.group.mypackage.Exception
не определено, то замените "my/group/mypackage/Exception"
на "java/lang/RuntimeException"
.
Перехват исключений из Java
См. Также фрагмент на coliru .
void rethrow_cpp_exception_as_java_exception()
{
try
{
throw; // This allows to determine the type of the 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) {
jclass jc = env->FindClass("java/lang/OutOfMemoryError");
if(jc) env->ThrowNew (jc, e.what());
}
catch (const std::ios_base::failure& e) {
jclass jc = env->FindClass("java/io/IOException");
if(jc) env->ThrowNew (jc, e.what());
}
catch (const std::exception& e) {
/* unknown exception (may derive from std::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 => "
"Improve rethrow_cpp_exception_as_java_exception()" );
}
}
Благодарю Mooing Duck за вклад в приведенный выше код C ++.
Адаптируйте сгенерированный JNI исходный код
Следующий файл Java_my_group_mypackage_example.cpp
использует вышеуказанную функцию rethrow_cpp_exception_as_java_exception()
:
JNIEXPORT jlong JNICALL Java_my_group_mypackage_example_function1
(JNIEnv *env, jobject object, jlong value)
{
try {
/* ... my processing ... */
return jlong(result);
} catch(...) {
rethrow_cpp_exception_as_java_exception();
return 0;
}
}
JNIEXPORT jstring JNICALL Java_my_group_mypackage_example_function2
(JNIEnv *env, jobject object, jlong value)
{
jstring jstr = 0
try {
/* ... my processing ... */
jstr = env->NewStringUTF("my result");
} catch(...) {
rethrow_cpp_exception_as_java_exception();
}
return jstr;
}
JNIEXPORT void JNICALL Java_my_group_mypackage_example_function3
(JNIEnv *env, jobject object, jlong value)
{
try {
/* ... my processing ... */
} catch(...) {
rethrow_cpp_exception_as_java_exception();
}
}
Соответствующий код Java
Файл example.java
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
}
}
Примечание: «my-DLL-name
» относится к динамической библиотеке, созданной из скомпилированного выше кода C / C ++. Это может быть my-DLL-name.dll
в Windows или my-DLL-name.so
в GNU / Linux / Unix.
Steps
Генерация example.class
из example.java
(используя javac
или maven или ваш любимый IDE Eclipse / Netbeans / IntelliJ IDEA /...)
Создание заголовочного файла C / C ++ Java_my_group_mypackage_example.h
из example.class
с использованием javah