memorandums

日々の生活で問題解決したこと、知ってよかったことなどを自分が思い出すために記録しています。

JNIとJNA

研究でJavaからCのプログラムを呼び出す必要がありましたので、JNIとJNAについて勉強してみました。メモまで残しておきます。

■JNI

  • C関数のインタフェースを記述したJavaクラス(TestJNI.java)を作成する。
public class TestJNI
{
  public native int add(int a, int b);
}
  • ビルドする。

javac TestJNI.java

  • javahでヘッダーファイル(TestJNI.h)作成する

javah -classpath . -d . TestJNI

  • TestJNI.hよりプロトタイプ宣言に仮引数を追加してCファイル(test_jni.c)にコピーして関数呼び出し部を実装する。(ポイント:C関数を呼び出す前後にJavaとCのプリミティブ型を対応づける処理が必要←ここが面倒)
int add(int a, int b) //既存の関数
{
  return (a + b);
}

JNIEXPORT jint JNICALL Java_Test_add
  (JNIEnv *env, jobject me, jint aj, jint bj)
{
  return add(aj, bj);   
}
  • 動的ライブラリを作成する。

gcc -I /System/Library/Frameworks/JavaVM.framework/Headers -dynamiclib -o libtest_jni.dylib test_jni.c

  • Javaクラス(TestJNI.java)実装する。
public class TestJNI
{
  public native int add(int a, int b);
  public static void main(String [] args)
  {
    System.loadLibrary("test_jni");
    TestJNI me = new TestJNI();
    System.out.println(me.add(100, 200));
  }
}
  • 実行する。

java TestJNI

■JNA

  • 事前準備 twall / jna https://github.com/twall/jna よりjna.jar(Version 4.1.0)をダウンロードして、/System/Library/Java/Extensions/にコピーする
  • C関数(test_jna.c)を作成する。
int add(int a, int b)
{
  return (a + b);
}
  • ビルドする。

gcc -dynamiclib -o libtest_jna.dylib test_jna.c

  • Javaクラスファイル(TestJNA.java)を作成する
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;

public class TestJNA
{
  public interface CLibrary extends Library {
    CLibrary INSTANCE = (CLibrary) Native.loadLibrary("test_jna", CLibrary.class);
    int add(int a, int b);
  }

  public static void main(String[] args) {
    System.out.println(CLibrary.INSTANCE.add(100, 200));
  }
}

javac TestJNA.java
java TestJNA

参考サイト

* ひしだま's ホームページ JNI(Java Native Interface)http://www.ne.jp/asahi/hishidama/home/tech/java/jni.html
* Mac OSXでダイナミックライブラリdylibを作ったり使ったりする方法 http://blog.katty.in/4346#