編集:下部のプリプロセッサマクロの代わりに関数を使用したこのエレガントな回答 も参照してください。
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
}
}
(またはEDIまたはMavenを使用して...)example.class
から生成します。次に、を使用してC /C++ヘッダーファイルを生成します。example.java
javac
Java_my_group_mypackage_example.h
example.class
javah
C /C++関数の宣言はにありJava_my_group_mypackage_example.h
ます。ここで、たとえば、これらの関数の定義(本体)を実装Java_my_group_mypackage_example.cpp
します。他のDLLからの例外をキャッチするには、(Cではなく)C++を使用することをお勧めします。
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を生成するためにコンパイルします。そのDLLを設定するPATH
か、Javaランタイムディレクトリ内に移動します(通常はtarget
)。
"my-DLL-name"
Javaソースコードを拡張子のないDLLの名前に置き換えることを忘れないでください(例: myname.dll
-> "myname"
)。
これは、Linux / Unix共有ライブラリを使用しても機能します(*.so
);-)