C言語からJavaのメソッドを呼び出す
/opt/blackdown-jdk-1.4.2以下にJavaがインストールしてある場合です.
linuxおよび,linuxエミュレータを導入しているFreeBSDでも実行できることを確認しました.ただし,この場合は,linux版のgccでコンパイルすることが必要です.
サンプルコード
以下のTest.javaを呼びだすC言語のコードを書くことにする.
public class Test{ public static void testmethod(){ System.out.println("succeseed of calling."); } public int sumation(int a, int b){ return a+b; } }
C言語側のコード
#include <jni.h> #include <stdio.h> #include <stdlib.h> int main(int argc, char **argv) { JNIEnv *env; JavaVM *jvm; JNIEnv jni; JavaVM vmi; JavaVMInitArgs vm_args; JavaVMOption options[4]; printf("beginning execution...?n"); /* * /opt/blackdown-jdk-1.4.2/がJavaのルートディレクトリの場合 */ options[0].optionString = (char *) ? "-Djava.class.path=.:/opt/blackdown-jdk-1.4.2/jre/lib/rt.jar"; options[1].optionString = (char *) "-Djava.compiler=NONE"; vm_args.version = JNI_VERSION_1_4; vm_args.options = options; vm_args.nOptions = 2; vm_args.ignoreUnrecognized = JNI_FALSE; /* * JavaVMを初期化,起動する * JNIインターフェースへのポインタを返す */ JNI_CreateJavaVM(&jvm,(void **)&env,&vm_args); jni = *env; vmi = *jvm; /* * クラスをさがす */ jclass cls = jni->FindClass(env, "Test"); if (cls == 0) { printf("cannot found Test?n"); exit(1); } /* * Methodをさがす * GetStaticMethodIDの引数については後述 */ jmethodID mid = jni->GetStaticMethodID(env, cls, "testmethod", "()V"); if (mid == 0) { printf("Could not locate method testmthod with signature ()V"); exit(1); } /* * 実行 */ jni->CallStaticVoidMethod(env, cls, mid, NULL); /* * VMを終了する */ vmi->DestroyJavaVM(jvm); }
コンパイルの仕方
...gccでインクルードパスを複数指定するときのデリミタってなかったっけ?
% gcc -I/opt/blackdown-jdk-1.4.2/include/ ? -I/opt/blackdown-jdk-1.4.2/include/linux ? -L/opt/blackdown-jdk-1.4.2/jre/lib/i386/client? -ljvm -lpthread test.c
jni.hと,jni.hの内部でincludeされているjni_md.hのある場所へのパスを通す必要がある.
また,リンクすべきlibjvm.soへのリンクパスも必要
実行
LD_LIBRARY_PATHにlibjvm.soのあるディレクトリが必要.私の環境では/opt/blackdown-jdk-1.4.2/
GetStaticMethodID
GetStaticMethodIDは,methodのIDを返す関数です.
このとき,3番目の引数であるメソッドの名前と,
4番目の引数であるメソッドの引数を引数とします.
この4番目の引数はJavaで定義されている内部表現によるものです.
型を自分で調べてもいいのですが,
たとえばString[]の配列などは([Ljava/lang/String;)Vなどとなり,結構面倒です.
なので,簡単に知るためにjavapというツールがあります.
Test.classで定義されているmethodについて調べたければ,
% javap -s Test
とすることで,
Compiled from Test.java public class Test extends java.lang.Test{ public Test(); /* ()V */ public stativ void testmthod(); /* ()V */ public int sumation(int, int); /* (II)I */ }
などの表示を得ることができます.