文字列 (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