1% BEGIN LICENSE BLOCK 2% Version: CMPL 1.1 3% 4% The contents of this file are subject to the Cisco-style Mozilla Public 5% License Version 1.1 (the "License"); you may not use this file except 6% in compliance with the License. You may obtain a copy of the License 7% at www.eclipse-clp.org/license. 8% 9% Software distributed under the License is distributed on an "AS IS" 10% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 11% the License for the specific language governing rights and limitations 12% under the License. 13% 14% The Original Code is The ECLiPSe Constraint Logic Programming System. 15% The Initial Developer of the Original Code is Cisco Systems, Inc. 16% Portions created by the Initial Developer are 17% Copyright (C) 2006 Cisco Systems, Inc. All Rights Reserved. 18% 19% Contributor(s): 20% 21% END LICENSE BLOCK 22 23%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 24% {\eclipse} Documentation 25% 26% $Id: embfunc.tex,v 1.1 2006/09/23 01:48:59 snovello Exp $ 27% 28%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 29\chapter{External Predicates in C and C++} 30\label{chapext} 31%HEVEA\cutdef[1]{section} 32 33\section{Coding External Predicates} 34 35External Predicates are C/C++ functions that can be called like predicates 36from \eclipse. 37Two following extra interface functions are provided for this purpose: 38\begin{description} 39\item[EC_word EC_arg(int i)] 40 returns the i'th argument of the predicate call. 41 42\item[pword ec_arg(int i)]\ \\ 43 same for C. 44 45\item[int unify(EC_word, EC_word)]\ \\ 46 unify two pwords. The return code indicates success or 47 failure. Note however, that if attributed variables are 48 involved, their handlers have not been invoked yet (this 49 happens after the external predicate returns). 50 51\item[int EC_word::unify(EC_word)]\ \\ 52 same as method. 53 54\item[int ec_unify(pword, pword)]\ \\ 55 same for C. 56\end{description} 57 58Apart from that, all functions for constructing, testing and decomposing 59{\eclipse} data can be used in writing the external predicate 60(see chapter \ref{chapmixed}). 61Here are two examples working with lists, the first one constructing 62a list in C: 63\begin{quote}\begin{verbatim} 64#include "eclipse.h" 65int 66p_string_to_list() /* string_to_list(+String, -List) */ 67{ 68 pword list; 69 char *s; 70 long len; 71 int res; 72 73 res = ec_get_string_length(ec_arg(1), &s, &len); 74 if (res != PSUCCEED) return res; 75 76 list = ec_nil(); /* build the list backwards */ 77 while (len--) 78 list = ec_list(ec_long(s[len]), list); 79 80 return ec_unify(ec_arg(2), list); 81} 82\end{verbatim}\end{quote} 83The next example uses an input list of integers and sums up the numbers. 84It is written in C++: 85\begin{quote}\begin{verbatim} 86#include "eclipseclass.h" 87extern "C" int 88p_sumlist() 89{ 90 int res; 91 long x, sum = 0; 92 EC_word list(EC_arg(1)); 93 EC_word car,cdr; 94 95 for ( ; list.is_list(car,cdr) == EC_succeed; list = cdr) 96 { 97 res = car.is_long(&x); 98 if (res != EC_succeed) return res; 99 sum += x; 100 } 101 res = list.is_nil(); 102 if (res != EC_succeed) return res; 103 return unify(EC_arg(2), EC_word(sum)); 104} 105\end{verbatim}\end{quote} 106The source code of these examples can be found in directory 107doc/examples within the {\eclipse} installation. 108 109\section{Compiling and loading} 110It is strongly recommended to copy the makefile "Makefile.external" 111provided in your installation directory under lib/\$ARCH and adapt it 112for your purposes. 113\index{Makefile} 114If the makefile is not used, the command to compile a C source 115with {\eclipse} library calls looks something like this: 116\begin{verbatim} 117 % cc -G -I/usr/local/eclipse/include/sparc_sunos5 118 -o eg_externals.so eg_externals.c 119\end{verbatim} 120or 121\begin{verbatim} 122 % cc -shared -I/usr/local/eclipse/include/i386_linux 123 -o eg_externals.so eg_externals.c 124\end{verbatim} 125If the external is to be used in a standalone {\eclipse}, 126it is possible to dynamically load it 127using the \bipref{load/1}{../bips/kernel/externals/load-1.html} 128predicate: 129\begin{verbatim} 130 load("eg_externals.so") 131\end{verbatim} 132On older UNIX platforms without dynamic loading, the following method 133may work. Compile the source using 134\begin{verbatim} 135 % cc -c -I/usr/local/eclipse/include/sparc_sunos5 eg_externals.c 136\end{verbatim} 137and load it with a command like 138\begin{verbatim} 139 load("eg_externals.o -lg -lm") 140\end{verbatim} 141The details may vary depending on what compiler and operating system 142you use. Refer to the Makefile.external for details. 143 144Once the object file containing the C function has been loaded into 145{\eclipse}, the link between the function and a predicate name 146is made with 147\bipref{external/2}{../bips/kernel/externals/external-2.html} 148\begin{verbatim} 149 external(sumlist/2, p_sumlist) 150\end{verbatim} 151The new predicate can now be called like other predicates. 152Note that the 153\bipref{external/2}{../bips/kernel/externals/external-2.html} 154declaration must precede any call to the declared predicate, 155otherwise the {\eclipse} compiler will issue an {\em inconsistent 156redefinition} error. Alternatively, the 157\bipref{external/1}{../bips/kernel/externals/external-1.html} 158forward declaration can be used to prevent this. 159 160If the external is needed in the context of an {\eclipse} which is itself 161embedded in a C/C++ host program, then the external code can be 162compiled/linked together with the host program, and the link between function 163and predicate name can alternatively be made by calling the C function 164ec_external(), e.g. 165\begin{verbatim} 166 ec_external(ec_did("sumlist",2), p_sumlist, ec_did("eclipse")) 167\end{verbatim} 168This must be done after the embedded {\eclipse} has been initialised 169(and after the module that is supposed to contain the external predicate 170has already been created). 171 172 173\section{Restrictions and Recommendations} 174 175It is neither supported nor recommended practice to call ec_resume() 176from within an external predicate, because this would invariably lead 177to programs which are hard to understand and to get right. 178 179Currently, it is also not possible to post goals from within an 180external predicate, but that is a sensible programming style and 181will be supported in forthcoming releases. 182Posting events however is already possible now. 183 184%HEVEA\cutend 185