Node:A Simpler Way to Define C predicates, Previous:Creating the Linked Foreign Resource, Up:Calling C from Prolog



A Simpler Way to Define C Predicates

SP_define_c_predicate() defines a Prolog predicate such that when the Prolog predicate is called it will call a C function with a term corresponding to the Prolog goal. The arguments to the predicate can then be examined using the usual term access functions, e.g. SP_get_arg() (see Accessing Prolog Terms).

typedef int SP_CPredFun(SP_term_ref goal, void *stash);
int SP_define_c_predicate(char *name, int arity, char *module,
                          SP_CPredFun *proc, void *stash)

The Prolog predicate module:name/arity will be defined (the module module must already exist). The stash argument can be anything and is simply passed as the second argument to the C function proc.

The C function should return SP_SUCCESS for success and SP_FAILURE for failure. The C function may also use SP_fail() or SP_raise_exception() in which case the return value will be ignored.

static int square_it(SP_term_ref goal, void *stash)
{
        long arg1;
        SP_term_ref tmp = SP_new_term_ref();
        SP_term_ref square_term = SP_new_term_ref();
        long the_square;

        /* goal will be a term like square(42,X) */
        if (!SP_get_arg(1,goal,tmp)) /* extract first arg */
           return SP_FAILURE;   /* should not happen */
        if (!SP_get_integer(tmp,&arg1))
           return SP_FAILURE;   /* arg 1 not an integer */

        SP_put_integer(square_term, arg1*arg1);
        SP_get_arg(2,goal,tmp); /* extract second arg */

        /* Unify output argument.
           SP_put_integer(tmp,...) would *not* work!  */
        if (SP_unify(tmp, square_term))
           return SP_SUCCESS;
else return SP_FAILURE;
}

...
/* Install square_it as user:square/2 */
SP_define_c_predicate("square", 2, "user", square_it, NULL /* unused */);
...