[comp.lang.prolog] Prolog/C Term passing

alain@kulcs.uucp (Alain Callebaut) (11/17/89)

In article <2716@munnari.oz.au>, ok@mudla.cs.mu.OZ.AU (Richard O'Keefe) 
talks about passing Prolog terms between Prolog and C.  He works out an 
example in one system, and briefly refers to a feature of some other 
Prolog systems :
> Some Prolog systems expose their data structures directly to C code in
> order to make it easy for you to build Prolog terms in C.  ...
He argues that the system he treats in more detail, doesn't do that, 
leaving the implementors of that system free to improve their data 
structures any time they get a bright idea.  Instead, they provide a 
library package that can be used to access and construct terms. 

To illustrate that a hybrid program (mix of Prolog and C) does not have 
to be as complicated as it is with his system, let me describe how 
this all works in BIM_Prolog. 

The same example (a predicate, mainly written in C, that converts a 
floating point number to a list of characters representing its printed 
form), programmed in BIM_Prolog (and C) looks as follows. 


:- extern_predicate( float_to_chars(integer:r,real:i,bpterm) ) .
{ The arguments of float_to_chars/3 are :
   arg1 : integer return parameter indicating success or failure
   arg2 : real input parameter - the floating point number
   arg3 : a Prolog term - the list of characters }

float_to_chars( _Float , _Chars ) :-
   float_to_chars( 1 , _Float , _Chars ) . { 1 for success, otherwise fail }


#include <BIMprolog.h>	/* The BIM_Prolog external interface definitions */

int float_to_chars( flt , chars )
float flt;
Term chars;
{
   char buffer[28], c, *p;
   Atom nil;
   Term term_lst, term, term_char;

   nil = BIM_Prolog_string_to_atom( "nil" );
   sprintf( buffer , "%.17e" , flt );
   term_lst = BIM_Prolog_new_term();	/* Create a new term */
   term = term_lst;
   p = buffer;
   while ( c = *p++ )	/* Treat each char, further instantiating the term ... */
   {
      BIM_Prolog_unify_term_value( term , BPT_LIST );	/* to a list */
      BIM_Prolog_get_term_arg( term , 1 , &term_char );	/* with head */
      BIM_Prolog_unify_term_value( term_char , BPT_INTEGER , c ); /* the char */
      BIM_Prolog_get_term_arg( term , 2 , &term );	/* tail free by now */
   }
   BIM_Prolog_unify_term_value( term , BPT_ATOM , nil );/* tail is nil */

   return BIM_Prolog_unify_terms(chars,term_lst);
		/* Unify the new term with the argument term */

} /* float_to_chars */


As can be seen, with a cleanly designed, and highly functional external 
interface, it is possible to write clear hybrid programs.  As well the 
Prolog part as the C part is much simpler than in the other system. 
The Prolog predicate simply calls the external routine, and relies on 
unification of the return value to implement the normal Prolog unification 
of the result.  It is not necessary to call two extra predicates for 
converting and deallocating the externally constructed term, nor is it 
necessary to perform an explicit unification of the constructed term 
with the predicate's argument. 
The C routine can construct any Prolog term it wants, in a conventional 
procedural way.  It is not necessary to calculate how much space you 
will need and to allocate it in advance.  Just start creating a term and 
furhter instantiate it. 

I won't reply on the other topics that were illustrated (I don't have 
that much time).  Moreover, to my feeling, it is a violation of Netiquette 
to use the net for customer support. 

Alain Callebaut
K. U. Leuven
Dept. of Computer Science
Belgium

ok@mudla.cs.mu.OZ.AU (Richard O'Keefe) (11/18/89)

In article <1790@kulcs.kulcs.uucp>, alain@kulcs.uucp (Alain Callebaut) writes:

> In article <2716@munnari.oz.au>, ok@mudla.cs.mu.OZ.AU (Richard O'Keefe) 
> talks about passing Prolog terms between Prolog and C.> 
> To illustrate that a hybrid program (mix of Prolog and C) does not have 
> to be as complicated as it is with his system, let me describe how 
> this all works in BIM_Prolog. 

I would point out that the library package I referred to is not a "finished"
part of the Quintus Prolog system.  The interface can and should be criticised.

Callebaut shows how to do it in BIM_Prolog.  (It's a lot easier in Poplog.)
I'll have to take his word for it that it's "clear" and "simple" in that
system.  The C code doesn't appear to be any shorter.  As a purely personal
comment, I find doing unification in C most unclear.  What happens if the
unification fails?  If the C code creates enough structure so that the
Prolog copy stack overflows, how does the Prolog garbage collector find the
C variables that refer to live structures?

> It is not necessary to call two extra predicates for 
> converting and deallocating the externally constructed term, nor is it 
> necessary to perform an explicit unification of the constructed term 
> with the predicate's argument. 

The difference in the Prolog side of my example and the Prolog side of
Callebaut's example is simply this:  term passing is directly built into
the BIM_Prolog/C interface and is not directly built into the Quintus/C
interface.  That's all it means.

> Moreover, to my feeling, it is a violation of Netiquette
> to use the net for customer support. 

I'm not quite sure what Callebaut means here.  His address is Dept. of
Computer Science, KUL.  Is he speaking of his customers?  ***I*** haven't
any customers.  I left Quintus at the end of '88.  If someone asks a
question on the net I really don't see why I shouldn't answer it; no-one
is paying me for this.  As for customer support over the net being a
violation of netiquette, the Sun customers who post so many questions to
comp.sys.sun and the Apollo customers who post so many questions to
comp.sys.apollo would treat anyone who told Sun or Apollo not to answer
any of those questions as the Bacchantes treated Orpheus.