6.8.3 Exceptions from C

Consider, for example, a function returning 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>
/* math_glue.h is generated by splfr from the foreign/[2,3] facts. 
   Always include the glue header in your foreign resource code.
#include "math_glue.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 4.3.2 …
Licensed to SICS
| ?- [math].
% compiling …/math.pl...
%  loading foreign resource …/math.so in module user
% compiled …/math.pl in module user, 0 msec 2400 bytes
| ?- sqrt(5.0,X).
X = 2.23606797749979 ? 
| ?- sqrt(a,X).
! Type error in argument 1 of user:sqrt/2
! expected a number, but found a
! goal:  user:sqrt(a,_110)
| ?- sqrt(-5,X).
! Domain error in argument 1 of user:sqrt/1
! expected '>=0.0', but found -5.0
! goal:  sqrt(-5.0)

Send feedback on this subject.