トップ 差分 一覧 Farm ソース 検索 ヘルプ PDF RSS ログイン

C言語からJavaのメソッドを呼び出す

[プログラミング]
[Java]
[C言語]

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

などの表示を得ることができます.