Prolog is a straight-forward way to implement simple logic rules and do the query of the system. GProlog(gprolog) is the GNU version of Prolog implementation. To leverage the power of gprolog into our system code (C/C++), there are usually 2 ways – using IPC or C interface. (GProlog dev usually call C/C++ in the GProlog). This post is focusing on calling GProlog in C using GProlog C interfaces. Thanks Sean and Michal from GNU Prolog User forum for answering my questions. Have fun~
0. Reference
http://gprolog.univ-paris1.fr/manual/gprolog.html#sec371
http://gnu-prolog.996310.n3.nabble.com/How-to-get-the-return-value-from-gprolog-in-C-td1166.html
http://gnu-prolog.996310.n3.nabble.com/Is-that-possible-to-call-dynamic-function-in-the-C-interface-td1177.html
1. IPC
The reason we would not like to do IPC with GProlog is the performance. Even though IPC with pipes is not that slow, the performance bottle neck may be the IPC if all other (C/C++) stuffs in the code run fast.
2. Calling the GProlog in C using GProlog C/C++ interface
Recalling the common patterns used in the interactive gprolog interpreter, we need to handle 3 calling/passing styles in the C code. All the code/examples are based on the pl file below:
% Dynamic function definition
:- dynamic(parent/2).
parent(bob,mary).
parent(jane,mary).
parent(mary,peter).
parent(paul,peter).
parent(peter,john).
anc(X, Y) :-
parent(X, Y).
anc(X, Z) :-
parent(X, Y),
anc(Y, Z).
a. solution query – anc(X, john).
func = Pl_Find_Atom(“anc”);
Pl_Query_Begin(PL_TRUE);
arg[0] = Pl_Mk_Variable();
arg[1] = Pl_Mk_String(n2);
nb_sol = 0;
res = Pl_Query_Call(func, 2, arg);
while (res)
{
sol[nb_sol++] = Pl_Rd_String(arg[0]);
res = Pl_Query_Next_Solution();
}
Pl_Query_End(PL_RECOVER);
b. judgement query – anc(john, bob).
func = Pl_Find_Atom(“anc”);
Pl_Query_Begin(PL_TRUE);
arg[0] = Pl_Mk_String(n1);
arg[1] = Pl_Mk_String(n2);
res = Pl_Query_Call(func, 2, arg);
Pl_Query_End(PL_RECOVER);
c. dynamic function – asserta(parent(dave, john)).
func = Pl_Find_Atom(“parent”);
Pl_Query_Begin(PL_TRUE);
arg[0] = Pl_Mk_String(n1);
arg[1] = Pl_Mk_String(n2);
arg2[0] = Pl_Mk_Callable(func, 2, arg);
func = Pl_Find_Atom(“asserta”);
res = Pl_Query_Call(func, 1, arg2);
3. The power of gplc
gplc is eventually a wrapper for gcc, which allows you to compile pl and C file the same time to generate the binary containing all the logic functionalities you need in GProlog. More over, all the gcc parameters could be passed from gplc. For details, please refer to the code repo down there.
4. R.t.D.C. – Read the Damn Code