まぁ、まずはJNIから
JavaにはJNIっていう、メソッドをC/C++で書ける機能があります *1。
例えば次のようにmainすらnative化出来たりしますね
public class HelloWorld { static { System.loadLibrary("hw"); } public static native void main(String[] args); }
これを実行できるようにするにはクラスファイルの作成とネイティブ部分のDLLを作るという二度手間になります。
まぁ、まずはネイティブ用のヘッダを吐き出して、
$ javac HelloWorld.java # コンパイル $ javah HelloWorld # ネイティブ関数用ヘッダを作成
このヘッダを使ったプログラムを次のように実装しておきます。
#include <iostream> #include "HelloWorld.h" JNIEXPORT void JNICALL Java_HelloWorld_main(JNIEnv* env, jclass cls, jobjectArray args) { std::cout << "Hello, World!" << std::endl; jsize length = env->GetArrayLength(args); for (jsize i = 0; i < length; i++) { jstring arg = (jstring) env->GetObjectArrayElement(args, i); const char* buf = env->GetStringUTFChars(arg, NULL); std::cout << "Arg " << i << " = " << buf << std::endl; env->ReleaseStringUTFChars(arg, buf); } }
で、これをDLLにします。まずはVC++の場合
$ cl /nologo /EHsc /I%JAVA_HOME%\include /I%JAVA_HOME%\include\win32 /Fehw HelloWorld.cpp
次にGCCの場合。あ、ココで使ったGCCはTDM-GCCの4.6.2です。
$ g++ -I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32 -c HelloWorld.cpp $ g++ -shared -o hw.dll HelloWorld.o -Wl,--kill-at
でまぁ、これでhw.dllが出来たので *2 実行すれば「Hello, World!」に続いて与えた引数がだらだらと垂れ流されます。
で、GCJ
GCJってのはGNUのGCC系列にあるJavaコンパイラです。Javaのソースもしくはクラスファイルから実行可能ファイルを作成できるネイティブコンパイラですね。
ただWindowsだとCygwinのGCCでしか利用できないのがネックですが *3
ようやく本題
問題はここで、上記のWindows DLLを使ったJavaプログラムをCygwin GCJでネイティブ化した時にどうやってnativeメソッドを使えるようにするか、です
GCCで作ったDLLの場合
ビルド時に-Wl,--kill-atとか-sharedを付けた効果かはよくわかりませんが、hw.dllをlibhw.dllにするだけで動きます。というかコピーとかいらずにhw.dll→libhw.dllというシンボリックリンクでも無問題でした。さすがや(∩´∀`)∩ワーイ *4
VC++で作ったDLLの場合
GCC版で気を良くしたのでシンボリックリンクにしたらUnsatisfiedLinkErrorが出おった(´・ω・`)
なんでかというと、JNIEXPORTついてるけど__declspec(dllexport)になってないようでエクスポートされてなかった。仕方ないので.defを作る。
$ nm HelloWorld.obj | grep -e "T _"
ってするとそれっぽい関数の定義が出てくるので、最後の@以降を削った上で.defに書く。出来上がる.defは↓のようにEXPORTS行の下に関数名を並べるらしい。
EXPORTS
Java_HelloWorld_main
それで、DLL作成時にコレも渡してやる。
$ cl /nologo /EHsc /I%JAVA_HOME%\include /I%JAVA_HOME%\include\win32 /Fehw HelloWorld.cpp hw.def
こうして出来上がったDLLならlibhw.dllにシンボリックリンク貼るもしくはリネームで利用可能になりました
参考
- Engineering HowTos - CProgHowTos
- 最初ココ見たけど実は.libが不要だった件
- WindowsでgccでDLL作成 - 偏った言語信者の垂れ流し
- GCCでDLLを作る方法。
- Win32/WinDll-Make - 備忘録
- モジュール定義ファイル (.defファイル) を使ったDLL作成方法