Path: utzoo!attcan!uunet!lll-winken!sun-barr!cs.utexas.edu!usc!snorkelwacker!bloom-beacon!eru!luth!sunic!mcsun!prlb2!prlbcom!kulcs!alain From: alain@kulcs.uucp (Alain Callebaut) Newsgroups: comp.lang.prolog Subject: Prolog/C Term passing Message-ID: <1790@kulcs.kulcs.uucp> Date: 17 Nov 89 12:01:11 GMT Reply-To: alain@kulcs.UUCP () Organization: Katholieke Universiteit Leuven, Dept. Computer Science Lines: 83 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 /* 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