Node:Exceptions from C, Next:, Previous:I/O on Lists of Character Codes, Up:Mixing Examples



Exceptions from C

Consider, for example, a function which returns the square root of its argument after checking that the argument is valid. If the argument is invalid, the function should raise an exception instead.

/* math.c */

#include <math.h>
#include <stdio.h>
#include <sicstus/sicstus.h>

extern double sqrt_check(double d);
double sqrt_check(double d)
{
  if (d < 0.0)
    {    /* build a domain_error/4 exception term */
      SP_term_ref culprit=SP_new_term_ref();
      SP_term_ref argno=SP_new_term_ref();
      SP_term_ref expdomain=SP_new_term_ref();
      SP_term_ref t1=SP_new_term_ref();

      SP_put_float(culprit, d);
      SP_put_integer(argno, 1);
      SP_put_string(expdomain, ">=0.0");
      SP_cons_functor(t1, SP_atom_from_string("sqrt"), 1, culprit);
      SP_cons_functor(t1, SP_atom_from_string("domain_error"), 4,
                      t1, argno, expdomain, culprit);
      SP_raise_exception(t1);    /* raise the exception */
      return 0.0;
    }
  return sqrt(d);
}

The Prolog interface to this function is defined in a file math.pl. The function uses the sqrt() library function, and so the math library -lm has to be included:

/* math.pl */

foreign_resource(math, [sqrt_check]).

foreign(sqrt_check, c, sqrt(+float, [-float])).

:- load_foreign_resource(math).

A linked foreign resource is created:

% splfr math.pl math.c -lm

A simple session using this function could be:

% sicstus
SICStus 3.9 (sparc-solaris-5.7): Thu Aug 19 16:25:28 MET DST 1999
Licensed to SICS
| ?- [math].
% consulting /home/san/pl/math.pl...
% /home/san/pl/math.pl consulted, 10 msec 816 bytes

yes
| ?- sqrt(5.0,X).

X = 2.23606797749979 ?

yes
| ?- sqrt(a,X).
! Type error in argument 1 of user:sqrt/2
! number expected, but a found
! goal:  sqrt(a,_143)

| ?- sqrt(-5,X).
! Domain error in argument 1 of user:sqrt/1
! expected '>=0.0', found -5.0
! goal:  sqrt(-5.0)

The above example used the foreign language interface with dynamic linking. To statically link math.s.o with the Prolog emulator, the following steps would have been taken:

% splfr -S math.pl math.c -lm
SICStus 3.9 (sparc-solaris-5.7): Thu Aug 19 16:25:28 MET DST 1999
Licensed to SICS
% spXxQwsr.c generated, 0 msec

yes
% spld -D -o mathsp --resources=./math.s.o
SICStus 3.9 (sparc-solaris-5.7): Thu Aug 19 16:25:28 MET DST 1999
Licensed to SICS
% spYdLTgi1.c generated, 0 msec

yes
Created "mathsp"
% ./mathsp
SICStus 3.9 (sparc-solaris-5.7): Thu Aug 19 16:25:28 MET DST 1999
Licensed to SICS
| ?- [math].
% consulting /a/filur/export/labs/isl/sicstus/jojo/sicstus38p/math.pl...
% consulted /a/filur/export/labs/isl/sicstus/jojo/sicstus38p/math.pl in module user, 0 msec 960 bytes

yes
| ?- sqrt(5.0,X).

X = 2.23606797749979 ?

yes