Na podstawie własnych doświadczeń. Aby utworzyć, skompilować i załądować do pamieci obiekty LogTalk'a konieczne jest wcześniejsze skonfigurowanie używanego kompilatora Prolog'a. Na potrzeby tego projektu zakładam, że jest nim SWI-Prolog, jakkolwiek jeśli wierzyć dokumentacji LogTalk'a to jest on w pełni kompatybilny z większościa innych kompilatorów Prolog'a.
Aby zintegrować LogTalk'a z SWI:
należy wykonać predykat consult na trzech plikach, które można znaleźć w katalogu instalacyjnym LogTalk'a :
configs/swi.config - ustawia zmienne i konfiguruj srodowisko Prologa
complier/logtalk.pl - laduje kompilator LogTalka
libpaths/libpaths.pl - ustawia sciezki do bibliotek standardowych LogTalka
chyba najwygodniej jest sporządzić sobie plik startowy:
:-consult('lib/Resources/logtalk/swi.config').
:-consult('lib/Resources/logtalk/logtalk.pl').
:-consult('lib/Resources/logtalk/libpaths.pl').
który pożniej uruchamiamy z Javy przed tworzeniem obiektów LogTalk, w następujący sposób:
JPL.setDefaultInitArgs(
new String[] {
"pl",
"-f", "none",
"-g", "set_prolog_flag(debug_on_error,false)",
"-q",
"-nosignals"
}
);
Query q = new Query("['lib/logtalkLoad.pl'].");
if (!q.hasSolution())
{
RuntimeException e = new RuntimeException("error loading logtalk");
}
else
{
System.out.println("Hurray!");
}
Po udanym wykonaniu powyższego kodu jesteśmy już w stanie tworzyć obiekty LogTalk z kodu Javy i wywoływać ich metody :
//utworznie instancji obiektu logTalkControler
Query loadControler = new Query("logtalk_load",
new Term[]{
new Atom("logTalkControler")
}
);
//wywolanie metody testValue obiektu logTalkControler
Query askLgt = new Query("logTalkControler::testValue(valueToTest).");
System.out.println("Is 'a' a proper TestValue?:"
+ (askLgt("testValue", "a")?"YES":"NO!"));
Pełną treść tego przykładu zamieszczam tutaj logtalkjava.
Niestety dalej natrafiam na problemy z próba uruchomienia komunikacji w drugą strone, tzn wywołania kodu Javy z LogTalka. Mimo iż modul jpl bardzo dobrze się sprawdza przy tworzeniu obiektów Javy, jak widać np w tym przykładzie :
:-use_module(library(jpl)).
jpl_test:-
jpl_new('javax.swing.JFrame', ['Frame with dialog'], F),
jpl_call(F, setLocation, [400, 300], _),
jpl_call(F, setSize, [400, 300], _),
jpl_call(F, setVisible, [@(true)], _),
jpl_call(F, toFront, [], _),
jpl_call('javax.swing.JOptionPane', showInputDialog, [F, 'Write sth'], N),
jpl_call(F, dispose, [], _),
( N == @(null) ->
write('You cancelled');
write('You typed'), write(N)
),
nl.
:-jpl_test.
Działa bez zarzutu, wyświetlając okienko dialogowe. Ale już próba uruchomienia podobnego kodu w metodzie obiektu LogTalk:
:-use_module(library(jpl),[jpl_new/3, jpl_call/4]).
:-object(logTalkControler).
:-public(toString/0).
:-public(testValue/1).
:-public(jpl_test/0).
:-initialization(
write('Constructor speaking')).
test(a).
test(b).
test(c).
value(a).
testValue(X) :-
test(X),
value(X).
jpl_test:-
jpl_new('javax.swing.JFrame', ['Frame with dialog'], F),
jpl_call(F, setLocation, [400, 300], _),
jpl_call(F, setSize, [400, 300], _),
jpl_call(F, setVisible, [@(true)], _),
jpl_call(F, toFront, [], _).
:-end_object.
Powoduje dość ciekawy komunikat przy próbie kompilacji w swi :
63 ?- logtalk_load(logTalkControler).
<<< reloading source file logTalkControler...
>>> compiling source file logTalkControler...
compiling object logTalkControler...
WARNING! These predicates are called but never defined: jpl_call/4, jpl_new/3
compiled object logTalkControler...
>>> logTalkControler source file compiled
WARNING! Redefining object logTalkControler
Constructor speaking
% logTalkControler.pl compiled 0.00 sec, 92 bytes
<<< logTalkControler source file reloaded
(1 compilation warning and 1 loading warning)
true.
64 ?- logTalkControler::jpl_test.
ERROR: Undefined procedure: jpl_new/3
ERROR: However, there are definitions for:
ERROR: jpl_new/3
I oczywiście nie działa. Podejrzewam, że problem tkwi w niewłaściwie dodanym pakiecie. Ale nie udało mi się jeszcze znaleźć rozwiązania..
Opierając się na przykładzie znalezionym na stronie jednym z sposobów integracji obiektów LogTalk z Java jest użycie jednego z pakietów SWI_Prolog, JPL : Java to Prolog Interface.
JPL który oferuje dwustronny interface pomiędzy Prologiem a Java.
Probując wywołać predykat Prologa z kodu Javy posługujemy się następującą składnią :
Query q2 =
new Query(
"child_of",
new Term[] {new Atom("joe"),new Atom("ralf")}
);
System.out.println(
"child_of(joe,ralf) is " +
( q2.query() ? "provable" : "not provable" )
);
Przykład pokazuje przesłanie zapytania do bazy wiedzy prologa. Można ten mechanizm wykorzystać do wywoływania predykatów wewnątrz obiektów LogTalk, czyli de facto do wywoływania metod na obiektach LogTalk z obiektów Java'y.
Gdy konieczne jest wysłanie komunikatu do obiektu Java'y z poziomu Prologa, JPL oferuje następujące rozwiązanie :
Predykat jpl_new/3 pozwala na utworzenie instancji obiektu klasy z Javy :
jpl_new( 'javax.swing.JFrame', ['frame with dialog'], F)
Natomiast predykat jpl_call/4 pozwala wywołać metodę na utworzonym powyżej obiekcie:
jpl_call( F, setVisible, [@(true)], _)
Jak widać JPL umożliwia obustronne wywoływanie metod pomiędzy obiektami klas zdefiniowanych w Javie i w Prologu. Jeżeli dodać do tego obiektowość oferowaną przez LogTalk to wydaje się, że jest to zestaw spełniający dane wymagania. Przykład całej klasy napisanej w Javie, służącej do komunikacji z obiektami LogTalk znajduje się tutaj LogTalkEngine