Javaから直接DLLを使いたいと思っていて,調べていたらJNI (Java Native Interface)とかあるんだけど,ヘッダファイルとかを作成しないと使えないらしく,もっと簡単にDLLを呼び出す方法が,JNAということらしい。
JNAは,JNIより簡単にJavaとC/C++をつなぐ「JNA」とはとかWindows APIをJavaから呼び出す(JNA)とかWindows64bitでJNAでJavaからC++コード呼び出そうとしてハマった話を参考にしつつJNAのサイトhttps://github.com/twall/jnaのGetting Startを動作させてみた。
とりあえずテキストというかターミナルで作業してみた。
JNAサイトから落としてきた,jna-4.0.0.jarとjna-platform-4.0.0.jarはソースと同じディレクトリフォルダに置くこととした。
サンプルソース
HelloWorld.java
import com.sun.jna.Library; import com.sun.jna.Native; import com.sun.jna.Platform; /** Simple example of JNA interface mapping and usage. */ public class HelloWorld { // This is the standard, stable way of mapping, which supports extensive // customization and mapping of Java to native types. public interface CLibrary extends Library { CLibrary INSTANCE = (CLibrary) Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"), CLibrary.class); void printf(String format, Object... args); } public static void main(String[] args) { CLibrary.INSTANCE.printf("Hello, World\n"); for (int i=0;i < args.length;i++) { CLibrary.INSTANCE.printf("Argument %d: %s\n", i, args[i]); } } }
コンパイル
javac -cp .;jna-4.0.0.jar;jna-platform-4.0.0.jar HelloWorld.java
実行
java -cp .;jna-4.0.0.jar;jna-platform-4.0.0.jar HelloWorld Hello, World
というわけで,Windows Nativeのprintfを使うことができた。
ちなみにNetBeansの場合,プロジェクト・プロパティのライブラリにjnaとjna-platformを追加すれば大丈夫
はい,こちらの記事のメモです。> Windows 64-bit 実行可能ファイル (EXE, DLL)の判別方法
使いたいNativeなDLLが当然だけど,CやC++から呼び出すので構造体へのポインタを渡している。これをJNAのマッピングに当てはめるのは骨が折れそうなので,もう一段DLLをかませてみた。
そうするとJavaからDLLを呼び出すときに2つのDLLを呼ばないと
Exception in thread "main" java.lang.UnsatisfiedLinkError: Unable to load library 'dll/hello.dll'
とエラーとなってしまう。
とりあえず,init()とか関数を作っておいて呼び出してみたらうまくいったんだけど,
HelloWorld.MyDLLDLL.INSTANCE.getClass(); HelloWorld.MyDLL.INSTANCE.getClass();
INSTANCE.getClass()をコールしておけばよいみたい。(本当はどうするのが正解なんだろう?)
というわけで,こんな感じ。 hello.c
#include <stdio.h> int hello() { hellohello(); }
hellohello.c
#include <stdio.h> int hellohello() { printf("Hello World!\n"); }
HelloWorld.java
public class HelloWorld { public interface MyDLL extends Library { static String PATH = "dll/mydll.dll"; MyDLL INSTANCE = (MyDLL)Native.loadLibrary(PATH, MyDLL.class); void hello(); } public interface MyDLLDLL extends Library { static String PATH = "dll/mydlldll.dll"; MyDLLDLL INSTANCE = (MyDLLDLL)Native.loadLibrary(PATH, MyDLLDLL.class); void hellohello(); void init(); } public static void main(String[] args) { HelloWorld.MyDLLDLL.INSTANCE.getClass(); HelloWorld.MyDLL.INSTANCE.getClass(); HelloWorld.MyDLL.INSTANCE.hello(); } }
mydlldll.dllはmydll.dllにstaticにリンクしているはずなんだけどなぁ。 とりあえず,メモ