/************************************************************************* * * * YAP Prolog @(#)c_interface.h 2.2 * * Yap Prolog was developed at NCCUP - Universidade do Porto * * * * Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 * * * ************************************************************************** * * * File: YapInterface.h * * Last rev: 19/2/88 * * mods: * * comments: c_interface header file for YAP * * * *************************************************************************/ /** @file YapInterface.h */ #ifndef _yap_c_interface_h #define _yap_c_interface_h 1 #define __YAP_PROLOG__ 1 #ifndef YAPVERSION #define YAPVERSION 60000 //> default versison #endif #include "YapDefs.h" #if HAVE_STDARG_H #include #endif #include /** @defgroup c-interface YAP original C-interface @Ingroup ChYInterface Before describing in full detail how to interface to C code, we will examine a brief example. Assume the user requires a predicate `my_process_id(Id)` which succeeds when _Id_ unifies with the number of the process under which YAP is running. In this case we will create a `my_process.c` file containing the C-code described below. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c} #include "YAP/YapInterface.h" static int my_process_id(void) { YAP_Term pid = YAP_MkIntTerm(getpid()); YAP_Term out = YAP_ARG1; return(YAP_Unify(out,pid)); } void init_my_predicates() { YAP_UserCPredicate("my_process_id",my_process_id,1); } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The commands to compile the above file depend on the operating system. @{ */ /* __BEGIN_DECLS should be used at the beginning of the C declarations, so that C++ compilers don't mangle their names. __END_DECLS is used at the end of C declarations. */ #undef __BEGIN_DECLS #undef __END_DECLS #ifdef __cplusplus # define __BEGIN_DECLS extern "C" { # define __END_DECLS } #else # define __BEGIN_DECLS /* empty */ # define __END_DECLS /* empty */ #endif /* _cplusplus */ __BEGIN_DECLS #if defined(_MSC_VER) && defined(YAP_EXPORTS) #define X_API __declspec(dllexport) #else #define X_API #endif __END_DECLS /** * * Using the compiler: Under Linux you should use: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gcc -c -shared -fPIC my_process.c ld -shared -o my_process.so my_process.o ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Under WIN32 in a MINGW/CYGWIN environment, using the standard installation path you should use: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gcc -mno-cygwin -I "c:/Yap/include" -c my_process.c gcc -mno-cygwin "c:/Yap/bin/yap.dll" --shared -o my_process.dll my_process.o ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Under WIN32 in a pure CYGWIN environment, using the standard installation path, you should use: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gcc -I/usr/local -c my_process.c gcc -shared -o my_process.dll my_process.o /usr/local/bin/yap.dll ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ And could be loaded, under YAP, by executing the following Prolog goal ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ load_foreign_files(['my_process'],[],init_my_predicates). ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Note that since YAP4.3.3 you should not give the suffix for object files. YAP will deduce the correct suffix from the operating system it is running under. After loading that file the following Prolog goal ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ my_process_id(N) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ would unify N with the number of the process under which YAP is running. Having presented a full example, we will now examine in more detail the contents of the C source code file presented above. The include statement is used to make available to the C source code the macros for the handling of Prolog terms and also some YAP public definitions. The function `my_process_id` is the implementation, in C, of the desired predicate. Note that it returns an integer denoting the success of failure of the goal and also that it has no arguments even though the predicate being defined has one. In fact the arguments of a Prolog predicate written in C are accessed through macros, defined in the include file, with names _YAP_ARG1_, _YAP_ARG2_, ..., _YAP_ARG16_ or with _YAP_A_( _N_) where _N_ is the argument number (starting with 1). In the present case the function uses just one local variable of type `YAP_Term`, the type used for holding YAP terms, where the integer returned by the standard unix function `getpid()` is stored as an integer term (the conversion is done by `YAP_MkIntTerm(Int))`. Then it calls the pre-defined routine `YAP_Unify(YAP_Term, YAP_Term)` which in turn returns an integer denoting success or failure of the unification. The role of the procedure `init_my_predicates` is to make known to YAP, by calling YAP_UserCPredicate(), the predicates being defined in the file. This is in fact why, in the example above, init_my_predicates() was passed as the third argument to load_foreign_files/3. The rest of this appendix describes exhaustively how to interface C to YAP. @section Manipulating_Terms Terms This section provides information about the primitives available to the C programmer for manipulating Prolog terms. Several C typedefs are included in the header file `yap/YAPInterface.h` to describe, in a portable way, the C representation of Prolog terms. The user should write is programs using this macros to ensure portability of code across different versions of YAP. The more important typedef is _YAP_Term_ which is used to denote the type of a Prolog term. Terms, from a point of view of the C-programmer, can be classified as follows + uninstantiated variables + instantiated variables + integers + floating-point numbers + database references + atoms + pairs (lists) + compound terms The primitive YAP_Bool YAP_IsVarTerm(YAP_Term _t_) returns true iff its argument is an uninstantiated variable. Conversely the primitive
  • YAP_Bool YAP_NonVarTerm(YAP_Term _t_) returns true iff its argument is not a variable.
  • The user can create a new uninstantiated variable using the primitive The following primitives can be used to discriminate among the different types of non-variable terms: The next primitive gives the type of a Prolog term: The set of possible values is an enumerated type, with the following values: Next, we mention the primitives that allow one to destruct and construct terms. All the above primitives ensure that their result is \a dereferenced, i.e. that it is not a pointer to another term. The following primitives are provided for creating an integer term from an integer and to access the value of an integer term. where `YAP_Int` is a typedef for the C integer type appropriate for the machine or compiler in question (normally a long integer). The size of the allowed integers is implementation dependent but is always greater or equal to 24 bits: usually 32 bits on 32 bit machines, and 64 on 64 bit machines. The two following primitives play a similar role for floating-point terms where `flt` is a typedef for the appropriate C floating point type, nowadays a `double` The following primitives are provided for verifying whether a term is a big int, creating a term from a big integer and to access the value of a big int from a term. YAP must support bignum for the configuration you are using (check the YAP configuration and setup). For now, YAP only supports the GNU GMP library, and `void \*` will be a cast for `mpz_t`. Notice that [YAP_BigNumOfTerm](@ref YAP_BigNumOfTerm) requires the number to be already initialised. As an example, we show how to print a bignum: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ static int p_print_bignum(void) { mpz_t mz; if (!YAP_IsBigNumTerm(YAP_ARG1)) return FALSE; mpz_init(mz); YAP_BigNumOfTerm(YAP_ARG1, mz); gmp_printf("Shows up as %Zd\n", mz); mpz_clear(mz); return TRUE; } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Currently, no primitives are supplied to users for manipulating data base references. A special typedef `YAP_Atom` is provided to describe Prolog \a atoms (symbolic constants). The two following primitives can be used to manipulate atom terms The following primitives are available for associating atoms with their names The function [YAP_LookupAtom](@ref YAP_LookupAtom) looks up an atom in the standard hash table. The function [YAP_FullLookupAtom](@ref YAP_FullLookupAtom) will also search if the atom had been "hidden": this is useful for system maintenance from C code. The functor [YAP_AtomName](@ref YAP_AtomName) returns a pointer to the string for the atom. The following primitives handle constructing atoms from strings with wide characters, and vice-versa: The following primitive tells whether an atom needs wide atoms in its representation: The following primitive can be used to obtain the size of an atom in a representation-independent way: The next routines give users some control over the atom garbage collector. They allow the user to guarantee that an atom is not to be garbage collected (this is important if the atom is hold externally to the Prolog engine, allow it to be collected, and call a hook on garbage collection: A \a pair is a Prolog term which consists of a tuple of two Prolog terms designated as the \a head and the \a tail of the term. Pairs are most often used to build lists. The following primitives can be used to manipulate pairs: One can construct a new pair from two terms, or one can just build a pair whose head and tail are new unbound variables. Finally, one can fetch the head or the tail. The last function supports the common operation of constructing a list from an array of terms of size _sz_ in a simple sweep. Notice that the list constructors can call the garbage collector if there is not enough space in the global stack. A \a compound term consists of a \a functor and a sequence of terms with length equal to the \a arity of the functor. A functor, described in C by the typedef `Functor`, consists of an atom and of an integer. The following primitives were designed to manipulate compound terms and functors The [YAP_MkApplTerm() function constructs a new term, with functor _f_ (of arity _n_), and using an array _args_ of _n_ terms with _n_ equal to the arity of the functor. YAP_MkNewApplTerm() builds up a compound term whose arguments are unbound variables. [YAP_ArgOfTerm](@ref YAP_ArgOfTerm) gives an argument to a compound term. `argno` should be greater or equal to 1 and less or equal to the arity of the functor. [YAP_ArgsOfTerm](@ref YAP_ArgsOfTerm) returns a pointer to an array of arguments. Notice that the compound term constructors can call the garbage collector if there is not enough space in the global stack. YAP allows one to manipulate the functors of compound term. The function [YAP_FunctorOfTerm](@ref YAP_FunctorOfTerm) allows one to obtain a variable of type `YAP_Functor` with the functor to a term. The following functions then allow one to construct functors, and to obtain their name and arity. Note that the functor is essentially a pair formed by an atom, and arity. Constructing terms in the stack may lead to overflow. The routine verifies whether you have at least _min_ cells free in the stack, and it returns true if it has to ensure enough memory by calling the garbage collector and or stack shifter. The routine returns false if no memory is needed, and a negative number if it cannot provide enough memory. You can set _min_ to zero if you do not know how much room you need but you do know you do not need a big chunk at a single go. Usually, the routine would usually be called together with a long-jump to restart the code. Slots can also be used if there is small state. @section Unifying_Terms Unification YAP provides a single routine to attempt the unification of two Prolog terms. The routine may succeed or fail: The routine attempts to unify the terms _a_ and _b_ returning `TRUE` if the unification succeeds and `FALSE` otherwise. @section Manipulating_Strings Strings The YAP C-interface now includes an utility routine to copy a string represented as a list of a character codes to a previously allocated buffer The routine copies the list of character codes _String_ to a previously allocated buffer _buf_. The string including a terminating null character must fit in _bufsize_ characters, otherwise the routine will simply fail. The _StringToBuffer_ routine fails and generates an exception if _String_ is not a valid string. The C-interface also includes utility routines to do the reverse, that is, to copy a from a buffer to a list of character codes, to a difference list, or to a list of character atoms. The routines work either on strings of characters or strings of wide characters: Users are advised to use the _N_ version of the routines. Otherwise, the user-provided string must include a terminating null character. The C-interface function calls the parser on a sequence of characters stored at _buf_ and returns the resulting term. The user-provided string must include a terminating null character. Syntax errors will cause returning `FALSE` and binding _error_ to a Prolog term. These C-interface functions are useful when converting chunks of data to Prolog: Notice that they are unsafe, and may call the garbage collector. They return 0 on error. These C-interface functions are useful when converting Prolog lists to arrays: They return the number of integers scanned, up to a maximum of sz, and -1 on error. @section Memory_Allocation Memory Allocation The next routine can be used to ask space from the Prolog data-base: The routine returns a pointer to a buffer allocated from the code area, or `NULL` if sufficient space was not available. The space allocated with [YAP_AllocSpaceFromYAP](@ref YAP_AllocSpaceFromYAP) can be released back to YAP by using: The routine releases a buffer allocated from the code area. The system may crash if `buf` is not a valid pointer to a buffer in the code area. @section Controlling_Streams Controlling YAP Streams from `C` The C-Interface also provides the C-application with a measure of control over the YAP Input/Output system. The first routine allows one to find a file number given a current stream: This function gives the file descriptor for a currently available stream. Note that null streams and in memory streams do not have corresponding open streams, so the routine will return a negative. Moreover, YAP will not be aware of any direct operations on this stream, so information on, say, current stream position, may become stale. A second routine that is sometimes useful is: This routine closes the YAP Input/Output system except for the first three streams, that are always associated with the three standard Unix streams. It is most useful if you are doing `fork()`. Last, one may sometimes need to flush all streams: It is also useful before you do a `fork()`, or otherwise you may have trouble with unflushed output. The next routine allows a currently open file to become a stream. The routine receives as arguments a file descriptor, the true file name as a string, an atom with the user name, and a set of flags: The available flags are `YAP_INPUT_STREAM`, `YAP_OUTPUT_STREAM`, `YAP_APPEND_STREAM`, `YAP_PIPE_STREAM`, `YAP_TTY_STREAM`, `YAP_POPEN_STREAM`, `YAP_BINARY_STREAM`, and `YAP_SEEKABLE_STREAM`. By default, the stream is supposed to be at position 0. The argument _name_ gives the name by which YAP should know the new stream. @section Utility_Functions Utility Functions in `C` The C-Interface provides the C-application with a a number of utility functions that are useful. The first provides a way to insert a term into the data-base This function returns a pointer to a copy of the term in the database (or to NULL if the operation fails. The next functions provides a way to recover the term from the data-base: Notice that the semantics are the same as for [recorded/3](@ref recorded): this function creates a new copy of the term in the stack, with fresh variables. The function returns 0L if it cannot create a new term. Last, the next function allows one to recover space: Notice that any accesses using _handle_ after this operation may lead to a crash. The following functions are often required to compare terms. Succeed if two terms are actually the same term, as in [==/2](@ref qQqQ): The next function succeeds if two terms are variant terms, and returns 0 otherwise, as [=@=/2](@ref qQaAqQ): The next functions deal with numbering variables in terms: The next one returns the length of a well-formed list _t_, or `-1` otherwise: Last, this function succeeds if two terms are unifiable: [=@=/2](@ref qQaAqQ): The second function computes a hash function for a term, as in `term_hash/4`. The first three arguments follow `term_has/4`. The last argument indicates what to do if we find a variable: if `0` fail, otherwise ignore the variable. @section Calling_YAP_From_C From `C` back to Prolog There are several ways to call Prolog code from C-code. By default, the `YAP_RunGoal()` should be used for this task. It assumes the engine has been initialised before: Execute query _Goal_ and return 1 if the query succeeds, and 0 otherwise. The predicate returns 0 if failure, otherwise it will return an _YAP_Term_. Quite often, one wants to run a query once. In this case you should use _Goal_: The `YAP_RunGoal()` function makes sure to recover stack space at the end of execution. Prolog terms are pointers: a problem users often find is that the term _Goal_ may actually be moved around during the execution of `YAP_RunGoal()`, due to garbage collection or stack shifting. If this is possible, _Goal_ will become invalid after executing `YAP_RunGoal()`. In this case, it is a good idea to save _Goal_ slots, as shown next: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ long sl = YAP_InitSlot(scoreTerm); out = YAP_RunGoal(t); t = YAP_GetFromSlot(sl); YAP_RecoverSlots(1); if (out == 0) return FALSE; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @copydoc real The following functions complement _YAP_RunGoal_: The YAP_RunGoal() interface is designed to be very robust, but may not be the most efficient when repeated calls to the same goal are made and when there is no interest in processing exception. The YAP_EnterGoal() interface should have lower-overhead: Next, follows an example of how to use [YAP_EnterGoal](@ref YAP_EnterGoal): ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void runall(YAP_Term g) { YAP_dogoalinfo goalInfo; YAP_Term *goalArgs = YAP_ArraysOfTerm(g); YAP_Functor *goalFunctor = YAP_FunctorOfTerm(g); YAP_PredEntryPtr goalPred = YAP_FunctorToPred(goalFunctor); result = YAP_EnterGoal( goalPred, goalArgs, &goalInfo ); while (result) result = YAP_RetryGoal( &goalInfo ); YAP_LeaveGoal(TRUE, &goalInfo); } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ YAP allows calling a *new* Prolog interpreter from `C`. One way is to first construct a goal `G`, and then it is sufficient to perform: the result will be `FALSE`, if the goal failed, or `TRUE`, if the goal succeeded. In this case, the variables in _G_ will store the values they have been unified with. Execution only proceeds until finding the first solution to the goal, but you can call [findall/3](@ref findall) or friends if you need all the solutions. Notice that during execution, garbage collection or stack shifting may have moved the terms @section Module_Manipulation_in_C Module Manipulation in C YAP allows one to create a new module from C-code. To create the new code it is sufficient to call: Notice that the new module does not have any predicates associated and that it is not the current module. To find the current module, you can call: Given a module, you may want to obtain the corresponding name. This is possible by using: Notice that this function returns a term, and not an atom. You can [YAP_AtomOfTerm](@ref YAP_AtomOfTerm) to extract the corresponding Prolog atom. @section Miscellaneous_ChYFunctions Miscellaneous C Functions @section Writing_C Writing predicates in C We will distinguish two kinds of predicates: The first kind of predicates should be implemented as a C function with no arguments which should return zero if the predicate fails and a non-zero value otherwise. The predicate should be declared to YAP, in the initialization routine, with a call to