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