MY-NOTEBOOK

Thursday, October 1, 2009

JavaからDLLを使う,呼び出す(JNI,Windows)

JavaからDLLを呼び出して使う必要がある、どうしたらいいか。
→JNIを使えばよい。

既存にDLLがあったので、それをJavaから呼び出したいと思ったが、調べてみるとそれは無理らしい。
JNIでは、Javaのクラスファイルからヘッダファイルを生成するのだが、そのとき関数名と引数が決められてしまう。
つまり、既存のDLLがちょうとそれと同じ関数名と引数を持つことは(通常)ないので、既存のDLLを直接呼び出すことはできない。

JavaからDLLを呼び出す方法

Microsoftのサポートページ に説明があったので、それを参考にさせていただきました。(感謝)

TestJNI.java

public class TestJNI {
   public native void greetings();

   static {
      System.loadLibrary("greet");
   }

   public static void main(String args[]) {
      new TestJNI().greetings();
   }
}

greet.cpp


#include "TestJNI.h"
#include <stdio.h>

JNIEXPORT void JNICALL Java_TestJNI_greetings(JNIEnv *env,jobject jobj) {
   printf("Hello World!");
}

Makefile

  1. javac TestJNI.java にて TestJNI.class を生成
  2. javah -jni TestJNI にて TestJNI.h を生成
  3. greet.cpp (と TestJNI.h および インクルードファイル群 ) から cl を使って greet.dll を生成

これをMakefile で記述すると以下のようになる。

java_home = C:Javajdk1.6.0_14
javac     = $(java_home)binjavac
javah     = $(java_home)binjavah

cc = cl
rm = del


greet.dll : greet.cpp TestJNI.class TestJNI.h
	$(cc) greet.cpp -I$(java_home)include -I$(java_home)includewin32 -Fegreet.dll -LD

TestJNI.h : TestJNI.class
	$(javah) -jni TestJNI

TestJNI.class : TestJNI.java
	$(javac) TestJNI.java


clean :
	$(rm) TestJNI.class
	$(rm) TestJNI.h
	$(rm) greet.dll
	$(rm) greet.exp
	$(rm) greet.lib
	$(rm) greet.obj

※java_homeなど環境にあわせてパスを調整する必要があります。

namke と 実行

DOSプロンプトにて...

> nmake
> java TestJNI
Hello World!

※実行は、VisualStudio2005 の VisualStudio2005 コマンドプロンプト を使用しました。

注意点

コンパイル時に (MSのサポートの説明ページ通りに) -MD オプションをつけると、greet.dll は正常に作成されるものの、java TestJNI したときに以下のようなエラーが出る。

    Exception in thread "main" java.lang.UnsatisfiedLinkError: 
    greet.dll: Can't find dependent libraries
© 2006-2012 Tomoaki Oshima