JNI に挑戦

 COBOLCOBOLer)の延命治療に粉骨砕身するオープン系技術者としては、なんとか「自分=お釈迦様」、「COBOLCOBOLer)=孫悟空」にしたいものです。つまり、自分の手のひらの中で動いてほしいわけですね。

 ということで、昨日 OpenCOBOL のインストール方法をご紹介しましたが、実は最終的な目標は COBOL プログラムを Java から呼び出すことなのです。

 ただ、何かと融通の効かない COBOL 君です。いきなり Java から COBOL を呼び出すのは難しいので、Java - C - COBOL という構成で呼び出したいと思います。


 それに先立ち、今回は Java から呼び出すプログラムを C で作ってみましょう。

 まず、Java 側を作ります。

package bridge;

public class HelloCobol {
    static {
        // libHello.so のロード
        System.loadLibrary("Hello");
    }

    // ネイティブメソッドの宣言
    public native void sayHello();

    public static void main(String[] args) {
        HelloCobol helloCobol = new HelloCobol();
	
        helloCobol.sayHello();
    }
}

 このように書くと、libHello.so 内の sayHello() 関数を呼び出すことになります。パッケージ名は、なんでもいいですが、今回は bridge にしてみました。

 次にこのクラスから、javah コマンドを使って C(C++)のヘッダファイルを生成します。上記のクラスをコンパイルしたものを指定します。

$ javah -jni bridge.HelloCobol

 これで、以下のような bridge_HelloCobol.h というファイルができあがります。

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class bridge_HelloCobol */

#ifndef _Included_bridge_HelloCobol
#define _Included_bridge_HelloCobol
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     bridge_HelloCobol
 * Method:    sayHello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_bridge_HelloCobol_sayHello
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

 この中に Java から呼ばれる関数のプロトタイプ宣言がありますので、これを参考に以下のように C プログラムを作成します。ファイル名はなんでもいいのですが、ここではヘッダファイルにあわせて bridge_HelloCobol.c とします。

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

JNIEXPORT void JNICALL Java_bridge_HelloCobol_sayHello(JNIEnv *env, jobject obj) {
    printf("Hello, world!");
}

 これをコンパイルします。Java のインストール先が環境変数 JAVA_HOME に入っているものとします。

$ gcc -shared -I$JAVA_HOME/include/ -I$JAVA_HOME/include/linux/ bridge_HelloCobol.c -o libHello.so

 これで、libHello.so というファイルができあがります。

 この libHello.so をライブラリパスに置くか、javaコマンドラインオプションで java.library.path で置き場を指定することで、実行時に動的リンクすることができます。たとえば、/home/hoge/lib の中にあるとすれば以下のようなコマンドで実行可能です。もちろん、bridge.HelloCobol クラスはクラスパス上にある必要があります。

$ java -Djava.library.path=/home/hoge/lib bridge.HelloCobol
Hello, world!