This example shows how a nondeterminate query can be made from C. It also shows how you can get at the exception terms raised from a Prolog query from C.
brothers.pl
foreign(brothers, c, brothers).
foreign_file(brothers, [brothers]).
:- load_foreign_files(brothers, []),
abolish([foreign/3, foreign_file/2]).
:- extern(write(+term)). % Make write/1 callable from C
:- extern(karamazov(-atom)). % Make karamazov/1 callable from C
karamazov('Fyodor').
karamazov('Dmitri').
karamazov('Ivan').
karamazov('Alyosha').
brothers.c
#include <quintus/quintus.h>
/* lookup_predicate() is just a wrapper around QP_predicate()
that prints an error message if QP_predicate() fails.
It returns 1 if QP_predicate() succeeds and 0 if
QP_predicate() fails
*/
int lookup_predicate(name, arity, module, predref)
char * name;
int arity;
char * module;
QP_pred_ref * predref;
{
*predref = QP_predicate(name, arity, module);
if (*predref == QP_BAD_PREDREF) {
printf("%s:%s/%-d is not callable from C\n",
module, name, arity);
return 0;
} else {
return 1;
}
}
brothers.c
void brothers() /* brothers() is called from Prolog */
{
QP_pred_ref karam, write;
QP_qid query;
QP_atom bro;
int status;
if (!lookup_predicate("karamazov", 1, "user", &karam)) {
return;
}
if ((query = QP_open_query(karam, &bro)) == QP_BAD_QID) {
printf("Cannot open query\n");
return;
}
/* Get solutions one at a time */
while ((status = QP_next_solution(query)) == QP_SUCCESS) {
printf("%10s is a Karamazov\n",
QP_string_from_atom(bro));
}
QP_close_query(query);
if (status == QP_ERROR) {
/* Query raised an exception */
QP_term_ref error = QP_new_term_ref();
printf("Query signalled an exception\n");
if (QP_exception_term(error) == QP_ERROR) {
printf("Could not get at exception term\n");
return;
}
if (lookup_predicate("write", 1, "user", &write)) {
/* Call Prolog builtin write/1 to print the
exception term */
if (QP_query(write, error) != QP_SUCCESS) {
printf("Couldnt write exception term\n");
} else {
return;
}
}
}
}
To test the QP_exception_term() part of this example add
a clause for karamazov/1 like:
karamazov(_) :- raise_exception(karamazov(error)).