トップ 一覧 置換 検索 ヘルプ RSS ログイン

JNI、JNAの使い方の変更点

  • 追加された行はこのように表示されます。
  • 削除された行はこのように表示されます。
!!!はじめに
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
,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 <stdio.h>

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}}