文字列 (java.lang.String) を、Java から JNI を通して Native Method に渡し、さらに SICStus Prolog に渡して表示させてみる。
Input.java
import java.awt.*; import java.awt.event.*; public class Input extends Panel implements ActionListener{ TextField tf; public Input() { tf = new TextField(30); tf.addActionListener(this); setLayout(new BorderLayout()); add("Center", tf); initProlog(); } public void actionPerformed(ActionEvent e) { if (e.getSource() == tf) { String str = tf.getText(); System.out.println("Java > "+str); send(str); tf.setText(""); } } static { System.loadLibrary("jcpl"); } public native void send(String data); public native void initProlog(); public static void main(String args[]) { Frame f = new Frame(); Input i = new Input(); f.add("Center", i); f.pack(); f.show(); } } |
JNI を使用する以外は特別なところ無し。initProlog() は読んで字の如く SICStus の初期化を行なう (実際は cpl.c で初期化している)。
jc.c
#include <jni.h> #include <stdio.h> #include "Input.h" #include "cpl.h" JNIEXPORT void JNICALL Java_Input_initProlog(JNIEnv *env, jobject obj) { init(); } JNIEXPORT void JNICALL Java_Input_send(JNIEnv *env, jobject obj, jstring data) { const char *str = (*env)->GetStringUTFChars(env, data, 0); printf("C > %s\n", str); fflush(stdout); sendToPl(str); (*env)->ReleaseStringUTFChars(env, data, str); return ; } |
void init(); void sendToPl(); |
#include <stdio.h> #include <sicstus/sicstus.h> SP_pred_ref pred; SP_term_ref data; int goal; void init() { SP_initialize(0, NULL, NULL); SP_load("des.ql"); pred = SP_predicate("send", 1, ""); data = SP_new_term_ref(); } void sendToPl(char *arg) { SP_put_string(data, arg); goal = SP_query(pred, data); } |
init() で SICStus の初期化を行なっている。
int SP_initialize(int argc, char **argv, char *boot_path)
boot_path は、通常 $SP_PATH/bin らしい。 これはコンパイル済みの Runtime Library runtime.ql に書いてあるらしい。 NULL を指定した場合、環境変数 $SP_PATH を探し、$SP_PATH/bin/runtime.ql をロードする。 $SP_PATH すら設定していないと current directory を見に行くらしい。 この関数は、Runtime Library のロードに成功すると SP_SUCCESS を返し、失敗すると SP_ERROR を返す。
この SP_initialize() は、二度呼び出すと不可解なことが起こった。 同じバイナリの中で再度コールすると、コール自体は成功し、write/1 や assert/1 も成功しているが、listing/0 に失敗する。
int SP_load(char *ql_file)
で、成功すると SP_SUCCESS、失敗すると SP_ERROR を返す。
SP_pred_ref SP_predicate(char *name_string, long arity, char *module_string)
述語が見つからないと NULL を返す。第三引数に "" か NULL を指定すると、デフォルトの type-in モジュールが使われる。
int SP_put_string(SP_term_ref t, char *name)
int SP_query(SP_pred_ref predicate, SP_term_ref arg1, ...)
send(Data) :- write('SICStus > '), write(Data), nl. |
% javac Input.java % javah -jni Input % sicstus SICStus 3 #5: Wed Oct 29 16:57:09 JST 1997 | ?- fcompile(des). {fcompiling /home/yoshida/java/native/jpl/des.pl...} {/home/yoshida/java/native/jpl/des.pl fcompiled, 10 msec 496 bytes} yes | ?- halt. % spmkrs libjcpl.so +c jc.c cpl.c SICStus 3 #5: Wed Oct 29 16:57:09 JST 1997 {/tmp/01312aaa.c generated, 0 msec} yes % ls Input.class Input.java cpl.h des.ql libjcpl.so* Input.h cpl.c des.pl jc.c
実行すると入力用のウィンドウが現れ、打ち込んだ文字が Java、C、Prolog によって表示される。うーむ。
% java Input Java > yoshida C > yoshida SICStus > yoshida Java > udraw C > udraw SICStus > udraw