!!!はじめに 64bit Javaから32bitでコンパイルしたNativeは実行できないで注意。 Can't load IA 32-bit .dll on a AMD 64-bit platform のようなエラーが出る。 !!共有ライブラリの検索パスについて ,OS,JNI,JNA ,windows,PATH環境変数{{br}}java.library.path,PATH環境変数{{br}}jna.library.path ,Linux,LD_LIBRARY_PATH環境変数{{br}}java.library.path,LD_LIBRARY_PATH環境変数{{br}}jna.library.path !!!JNI JavaからNativeを呼ぶためのもの。 手順は以下のとおり。 +Javaプログラムの作成とコンパイル +Javaからヘッダファイル作成 +Cプログラムの作成とコンパイル +実行 !!Javaプログラムの作成とコンパイル !HelloWorldJNI.java {{code Java, public class HelloWorldJNI { static { // ライブラリをロードします System.loadLibrary("HelloWorldJNI"); } // ネイティブメソッドを宣言します public native void sayHelloWorld(); public static void main(String[] args) { HelloWorldJNI hello = new HelloWorldJNI(); hello.sayHelloWorld(); } } }} !コンパイル javac HelloWorldJNI.java !!Javaからヘッダファイル作成 !ヘッダファイル作成 javah HelloWorldJNI で HelloWorldJNI.h が作成される。 !!Cプログラムの作成とコンパイル !Cプログラムの作成 HelloWorldJNI.h のプロトタイプ宣言を確認してCプログラムを書く {{code Java, #include "HelloWorldJNI.h" JNIEXPORT void JNICALL Java_HelloWorldJNI_sayHelloWorld ( JNIEnv *env, jobject obj ) { printf("Hello World\n"); } }} !コンパイル(mingwの例) gnupack(mingw)を使った場合 gcc -shared HelloWorldJNI.c -Id:/java/include -Id:/java/include/win32 -Wl,--enable-auto-import -Wl,--add-stdcall-alias -o HelloWorldJNI.dll みたいな感じ。JDKのincludeとinclude/win32にincllude path を通す。 -Wl,--add-stdcall-alias を付けないと、実行時に関数が見つけられずエラーになるので注意。 また、gnupackでもmingw の場合は /d/java/include のような形式ではなく d:/java/include のようなパスの書き方をする。 !コンパイル(Linuxのgccの例) gcc -fPIC -shared HelloWorldJNI.c -I /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.25.x86_64/include -I /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.25.x86_64/include/linux/ -o libHelloWorldJNI.so Linuxの場合、共有ライブラリは lib****.so のように lib が先頭に着くので注意。 !!実行 !Windowsの場合 Windowsの場合は共有ライブラリは PATH環境変数 java.library.pathオプション から検索される。以下は実行例 java HelloWorldJNI java -Djava.library.path=d:/temp !Linuxの場合 Linuxの場合は共有ライブラリは LD_LIBRARY_PATH環境変数 java.library.pathオプション から検索される。以下は実行例 java HelloWorldJNI java -Djava.library.path=. HelloWorldJNI !!!JNA JNI より簡単にネイティブライブラリを使う。 !!例1 {{code Java, import com.sun.jna.Library; import com.sun.jna.Native; public class HelloWorld { public interface CLibrary extends Library { CLibrary INSTANCE = (CLibrary) Native.loadLibrary("msvcrt" , CLibrary.class); void printf(String format, Object... args); } public static void main(String[] args) { CLibrary.INSTANCE.printf("Hello, World\n"); } } }} !!例2 {{code Java, import com.sun.jna.Library; import com.sun.jna.Native; interface User32 extends Library { // インスタンス生成 User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class); // 関数へのインターフェース int MessageBoxA(int hWnd, byte[] lpText, byte[] lpCaption, int uType); // 定数定義 int MB_YESNO = 0x00000004; int MB_ICONASTERISK = 0x00000040; } public class test2 { public static void main(String[] args) throws Exception { User32 user32=User32.INSTANCE; user32.MessageBoxA(0, _T("終了しますか?"), _T("終了確認"), User32.MB_ICONASTERISK | User32.MB_YESNO); } // マルチバイト文字列を返す。 private static byte[] _T(final String str) throws Exception { return (str+"\0").getBytes("Windows-31J"); } } }} !!自分でDLLを作成し、JNAで呼び出す !hello.c {{code Java, #include void hello (){ printf("Hello!\n"); } }} !コンパイル Windowsの場合 gcc -shared -o hello.dll hello.c Linuxの場合 gcc -fPIC -shared -o libhello.so hello.c ※ライブラリ名に「lib」をつける必要があるので注意 !test.java {{code Java, import com.sun.jna.Library; import com.sun.jna.Native; interface HelloDLL extends Library { // インスタンス生成 HelloDLL INSTANCE = (HelloDLL) Native.loadLibrary("hello", HelloDLL.class); // 関数へのインターフェース void hello(); } public class test { public static void main(String[] args){ HelloDLL hello = HelloDLL.INSTANCE; hello.hello(); } } }} !実行 Windowsの場合 Linuxの場合はLD_LIBRARY_PATH環境変数で示すパスにsoファイルを置く必要がある。 export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH など。 Windowsの場合 Windowsの場合は共有ライブラリは PATH環境変数 jna.library.pathオプション から検索される。以下は実行例 java test java -Djna.library.path=d:/temp Linuxの場合 Linuxの場合は共有ライブラリは LD_LIBRARY_PATH環境変数 jna.library.pathオプション から検索される。以下は実行例 java test java -Djna.library.path=. test {{category2 プログラミング言語,Java}}