Calling a Nondeterminate Predicate

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)).