编辑: 另请参阅使用函数而不是底部预处理器宏的优雅答案。
如果你想实现JNI,我就是这样做的:
让我们想象一下文件中的以下类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
}
}
example.class
从example.java
(使用javac
或您的 EDI 或 maven ...)生成。然后Java_my_group_mypackage_example.h
使用. example.class
_javah
C/C++ 函数的声明在Java_my_group_mypackage_example.h
. 现在我们例如实现这些函数的定义(主体)Java_my_group_mypackage_example.cpp
。更喜欢使用 C++(而不是 C)来捕获来自其他 DLL 的异常。
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
}
C 预处理器宏CATCH_CPP_EXCEPTION_AND_THROW_JAVA_EXCEPTION
定义如下。它将 C++ 异常转换为 Java 异常。使用您自己的代码自定义该代码mypackage::Exception
并将其放在一个公共标头中(不在 `Java_my_group_mypackage_example.h' 中,因为它可以再次重新生成)。
#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
生成 DLL。PATH
在您的 java 运行时目录(通常target
)中设置或移动该 DLL。
不要忘记用"my-DLL-name"
不带扩展名的 DLL 名称替换 java 源代码中的名称(例如myname.dll
-> "myname"
)。
这也适用于 Linux/Unix 共享库 ( *.so
) ;-)