<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> <meta name="generator" content="hevea 2.05"> <meta name="Author" content="Daniel Diaz"> <meta name="Keywords" content="GNU Prolog, manual, Prolog, compiler, constraints, finite domains"> <link rel="icon" type="image/x-icon" href="/gprolog.ico"><link rel="stylesheet" type="text/css" href="gprolog.css"> <title>Calling C from Prolog</title> </head> <body TEXT=black BGCOLOR=white> <a href="gprolog067.html"><img src="previous_motif.gif" alt="Previous"></a> <a href="gprolog065.html"><img src="contents_motif.gif" alt="Up"></a> <a href="gprolog069.html"><img src="next_motif.gif" alt="Next"></a> <hr> <h3 class="subsection" id="sec337">10.3  Calling C from Prolog</h3> <ul> <li><a href="gprolog068.html#sec338">Introduction</a> </li><li><a href="gprolog068.html#foreign%2F2-directive"><span class="c003">foreign/2</span> directive </a> </li><li><a href="gprolog068.html#sec340">The C function</a> </li><li><a href="gprolog068.html#sec341">Input arguments</a> </li><li><a href="gprolog068.html#sec342">Output arguments</a> </li><li><a href="gprolog068.html#sec343">Input/output arguments</a> </li><li><a href="gprolog068.html#sec344">Writing non-deterministic C code</a> </li><li><a href="gprolog068.html#sec345">Example: input and output arguments</a> </li><li><a href="gprolog068.html#sec346">Example: non-deterministic code</a> </li><li><a href="gprolog068.html#sec347">Example: input/output arguments</a> </li></ul> <p> <a id="Calling-C-from-Prolog"></a></p> <h4 class="subsubsection" id="sec338">10.3.1  Introduction</h4> <p>This interface can then be used to write both simple and complex C routines. A simple routine uses either input or output arguments which type is simple. In that case the user does not need any knowledge of Prolog data structures since all Prolog ↔ C data conversions are implicitly achieved. To manipulate complex terms (lists, structures) a set of functions is provided. Finally it is also possible to write non-deterministic C code.</p> <h4 class="subsubsection" id="foreign/2-directive">10.3.2  <a id="hevea_default1015"></a><a id="hevea_default1016"></a><span class="c003">foreign/2</span> directive </h4> <p><span class="c003">foreign/2</span> directive (section <a href="gprolog022.html#foreign%2F2">7.1.15</a>) declares a C function interface. The general form is <span class="c003">foreign(Template, Options)</span> which defines an interface predicate whose prototype is <span class="c003">Template</span> according to the options given by <span class="c003">Options</span>. <span class="c003">Template</span> is a callable term specifying the type/mode of each argument of the associated Prolog predicate.</p><p><span class="c009">Foreign options</span>: <span class="c003">Options</span> is a list of foreign options. If this list contains contradictory options, the rightmost option is the one which applies. Possible options are:</p><ul class="itemize"><li class="li-itemize"><a id="hevea_default1017"></a><span class="c003">fct_name(F)</span>: <span class="c003">F</span> is an atom representing the name of the C function to call. By default the name of the C function is the same as the principal functor of <span class="c003">Template</span>. In any case, the atom associated with the name of the function must conforms to the syntax of C identifiers.</li><li class="li-itemize"><a id="hevea_default1018"></a><span class="c003">return(boolean</span>/<span class="c003">none</span>/<span class="c003">jump)</span>: specifies the value returned by the C function:<ul class="itemize"><li class="li-itemize"><a id="hevea_default1019"></a><span class="c003">boolean</span>: the type of the function is <span class="c003">PlBool</span> (returns <span class="c003">PL_TRUE</span> on success, <span class="c003">PL_FALSE</span> otherwise).</li><li class="li-itemize"><a id="hevea_default1020"></a><span class="c003">none</span>: the type of the function is <span class="c003">void</span> (no returned value).</li><li class="li-itemize"><a id="hevea_default1021"></a><span class="c003">jump</span>: the type of the function is <span class="c003">void(*)()</span> (returns the address of a Prolog code to execute).</li></ul><p>The default value is <span class="c003">boolean</span>.</p></li><li class="li-itemize"><a id="hevea_default1022"></a><span class="c003">bip_name(Name, Arity)</span>: initializes the error context with <span class="c003">Name</span> and <span class="c003">Arity</span>. If an error occurs this information is used to indicate from which predicate the error occurred (section <a href="gprolog020.html#General-format-and-error-context">6.3.1</a>). It is also possible to prevent the initialization of the error context using <span class="c003">bip_name(none)</span>. By default <span class="c003">Name</span> and <span class="c003">Arity</span> are set to the functor and arity of <span class="c003">Template</span>.</li><li class="li-itemize"><a id="hevea_default1023"></a><span class="c003">choice_size(N)</span>: this option specifies that the function implements a non-deterministic code. <span class="c003">N</span> is an integer specifying the size needed by the non-deterministic C function. This facility is explained later (section <a href="#Writing-non-deterministic-C-code">10.3.7</a>). By default a foreign function is deterministic.</li></ul><p><span class="c003">foreign(Template)</span> is equivalent to <span class="c003">foreign(Template, [])</span>.</p><p><span class="c009">Foreign modes and types</span>: each argument of <span class="c003">Template</span> specifies the foreign mode and type of the corresponding argument. This information is used to check the type of effective arguments at run-time and to perform Prolog ↔ C data conversions. Each argument of <span class="c003">Template</span> is formed with a mode symbol followed by a type name. Possible foreign modes are:</p><ul class="itemize"><li class="li-itemize"><span class="c003">+</span>: input argument.</li><li class="li-itemize"><span class="c003">-</span>: output argument.</li><li class="li-itemize"><span class="c003">?</span>: input/output argument.</li></ul><p>Possible foreign types are:</p><table class="c000 cellpadding1" border=1><tr><td class="c014"> Foreign type</td><td class="c014">Prolog type</td><td class="c014">C type</td><td class="c014">Description of the C type </td></tr> <tr><td class="c014"> <span class="c003">integer</span></td><td class="c014">integer</td><td class="c014"><span class="c003">PlLong</span></td><td class="c014">value of the integer </td></tr> <tr><td class="c014"> <span class="c003">positive</span></td><td class="c014">positive integer</td><td class="c014"><span class="c003">PlLong</span></td><td class="c014">value of the integer </td></tr> <tr><td class="c014"> <span class="c003">float</span></td><td class="c014">floating point number</td><td class="c014"><span class="c003">double</span></td><td class="c014">value of the floating point number </td></tr> <tr><td class="c014"> <span class="c003">number</span></td><td class="c014">number</td><td class="c014"><span class="c003">double</span></td><td class="c014">value of the number </td></tr> <tr><td class="c014"> <span class="c003">atom</span></td><td class="c014">atom</td><td class="c014"><span class="c003">PlLong</span></td><td class="c014">internal key of the atom </td></tr> <tr><td class="c014"> <span class="c003">boolean</span></td><td class="c014">boolean</td><td class="c014"><span class="c003">PlLong</span></td><td class="c014">value of the boolean (0=<span class="c003">false</span>, 1=<span class="c003">true</span>) </td></tr> <tr><td class="c014"> <span class="c003">char</span></td><td class="c014">character</td><td class="c014"><span class="c003">PlLong</span></td><td class="c014">value of (the code of) the character </td></tr> <tr><td class="c014"> <span class="c003">code</span></td><td class="c014">character code</td><td class="c014"><span class="c003">PlLong</span></td><td class="c014">value of the character-code </td></tr> <tr><td class="c014"> <span class="c003">byte</span></td><td class="c014">byte</td><td class="c014"><span class="c003">PlLong</span></td><td class="c014">value of the byte </td></tr> <tr><td class="c014"> <span class="c003">in_char</span></td><td class="c014">in-character</td><td class="c014"><span class="c003">PlLong</span></td><td class="c014">value of the character or <span class="c003">-1</span> for end-of-file </td></tr> <tr><td class="c014"> <span class="c003">in_code</span></td><td class="c014">in-character code</td><td class="c014"><span class="c003">PlLong</span></td><td class="c014">value of the character-code or <span class="c003">-1</span> for end-of-file </td></tr> <tr><td class="c014"> <span class="c003">in_byte</span></td><td class="c014">in-byte</td><td class="c014"><span class="c003">PlLong</span></td><td class="c014">value of the byte or <span class="c003">-1</span> for the end-of-file </td></tr> <tr><td class="c014"> <span class="c003">string</span></td><td class="c014">atom</td><td class="c014"><span class="c003">char *</span></td><td class="c014">C string containing the name of the atom </td></tr> <tr><td class="c014"> <span class="c003">chars</span></td><td class="c014">character list</td><td class="c014"><span class="c003">char *</span></td><td class="c014">C string containing the characters of the list </td></tr> <tr><td class="c014"> <span class="c003">codes</span></td><td class="c014">character-code list</td><td class="c014"><span class="c003">char *</span></td><td class="c014">C string containing the characters of the list </td></tr> <tr><td class="c014"> <span class="c003">term</span></td><td class="c014">Prolog term</td><td class="c014"><span class="c003">PlTerm</span></td><td class="c014">generic Prolog term </td></tr> </table><p><span class="c009">Simple foreign type</span>: a simple type is any foreign type listed in the above tabled except <span class="c003">term</span>. A simple foreign type is an atomic term (character and character-code lists are in fact lists of constants). Each simple foreign type is converted to/from a C type to simplify the writing of the C function.</p><p><span class="c009">Complex foreign type</span>: type foreign type <span class="c003">term</span> refers to any Prolog term (e.g. lists, structures…). When such an type is specified the argument is passed to the C function as a <span class="c003">PlTerm</span> (GNU Prolog C type equivalent to a <span class="c003">PlLong</span>). Several functions are provided to manipulate <span class="c003">PlTerm</span> variables (section <a href="gprolog069.html#Manipulating-Prolog-terms">10.4</a>). Since the original term is passed to the function it is possible to read its value or to unify it. So the meaning of the mode symbol is less significant. For this reason it is possible to omit the mode symbol. In that case <span class="c003">term</span> is equivalent to <span class="c003">+term</span>.</p> <h4 class="subsubsection" id="sec340">10.3.3  The C function</h4> <p>The type returned by the C function depends on the value of the <a id="hevea_default1024"></a><span class="c003">return</span> foreign option (section <a href="#foreign%2F2-directive">10.3.2</a>). If it is <a id="hevea_default1025"></a><span class="c003">boolean</span> then the C function is of type <span class="c003">PlBool</span> and shall return <span class="c003">PL_TRUE</span> in case of success and <span class="c003">PL_FALSE</span> otherwise. If the <span class="c003">return</span> option is <a id="hevea_default1026"></a><span class="c003">none</span> the C function is of type <span class="c003">void</span>. Finally if it is <a id="hevea_default1027"></a><span class="c003">jump</span>, the function shall return the address of a Prolog predicate and, at the exit of the function, the control is given to that predicate.</p><p>The type of the arguments of the C function depends on the mode and type declaration specified in <span class="c003">Template</span> for the corresponding argument as explained in the following sections.</p> <h4 class="subsubsection" id="sec341">10.3.4  Input arguments</h4> <p> <a id="Input-arguments"></a> An input argument is tested at run-time to check if its type conforms to the foreign type and then it is passed to the C function. The type of the associated C argument is given by the above table (section <a href="#foreign%2F2-directive">10.3.2</a>). For instance, the effective argument <span class="c003">Arg</span> associated with <span class="c003">+positive</span> foreign declaration is submitted to the following process:</p><ul class="itemize"><li class="li-itemize">if <span class="c003">Arg</span> is a variable an <span class="c003">instantiation_error</span> is raised.</li><li class="li-itemize">if <span class="c003">Arg</span> is neither a variable nor an integer a <span class="c003">type_error(integer, Arg)</span> is raised.</li><li class="li-itemize">if <span class="c003">Arg</span> is an integer < 0 a <span class="c003">domain_error(not_less_than_zero, Arg)</span> is raised.</li><li class="li-itemize">otherwise the value of <span class="c003">Arg</span> is passed to the C is passed to the C function as an integer (<span class="c003">PlLong</span>).</li></ul><p>When <span class="c003">+string</span> is specified the string passed to the function is the internal string of the corresponding atom and should not be modified.</p><p>When <span class="c003">+term</span> is specified the term passed to the function is the original Prolog term. It can be read and/or unified. It is also the case when <span class="c003">term</span> is specified without any mode symbol.</p> <h4 class="subsubsection" id="sec342">10.3.5  Output arguments</h4> <p> <a id="Output-arguments"></a> An output argument is tested at run-time to check if its type conforms to the foreign type and it is unified with the value set by the C function. The type of the associated C argument is a pointer to the type given by the above table (section <a href="#foreign%2F2-directive">10.3.2</a>). For instance, the effective argument <span class="c003">Arg</span> associated with <span class="c003">-positive</span> foreign declaration is handled as follows:</p><ul class="itemize"><li class="li-itemize">if <span class="c003">Arg</span> is neither a variable nor an integer a <span class="c003">type_error(integer, Arg)</span> is raised.</li><li class="li-itemize">if <span class="c003">Arg</span> is an integer < 0 a <span class="c003">domain_error(not_less_than_zero, Arg)</span> is raised.</li><li class="li-itemize">otherwise a pointer to an integer (<span class="c003">PlLong</span> <span class="c003">*</span>) is passed to the C function. If the function returns <span class="c003">PL_TRUE</span> the integer stored at this location is unified with <span class="c003">Arg</span>.</li></ul><p>When <span class="c003">-term</span> is specified, the function must construct a term into the its corresponding argument (which is of type <span class="c003">PlTerm *</span>). At the exit of the function this term will be unified with the actual predicate argument.</p> <h4 class="subsubsection" id="sec343">10.3.6  Input/output arguments</h4> <p> <a id="Input/output-arguments"></a> Basically an input/output argument is treated as in input argument if it is not a variable, as an output argument otherwise. The type of the associated C argument is a pointer to a <span class="c003">PlFIOArg</span> (GNU Prolog C type) defined as follows:</p><dl class="list"><dt class="dt-list"> </dt><dd class="dd-list"> <pre class="verbatim">typedef struct { PlBool is_var; PlBool unify; union { PlLong l; char *s; double d; }value; }PlFIOArg; </pre></dd></dl><p>The field <span class="c003">is_var</span> is set to <span class="c003">PL_TRUE</span> if the argument is a variable and <span class="c003">PL_FALSE</span> otherwise. This value can be tested by the C function to determine which treatment to perform. The field <span class="c003">unify</span> controls whether the effective argument must be unified at the exit of the C function. Initially <span class="c003">unify</span> is set to the same value as <span class="c003">is_var</span> (i.e. a variable argument will be unified while a non-variable argument will not) but it can be modified by the C function. The field <span class="c003">value</span> stores the value of the argument. It is declared as a C <span class="c003">union</span> since there are several kinds of value types. The field <span class="c003">s</span> is used for C strings, <span class="c003">d</span> for C doubles and <span class="c003">l</span> otherwise (<span class="c003">int</span>, <span class="c003">PlLong</span>, <span class="c003">PlTerm</span>). if <span class="c003">is_var</span> is <span class="c003">PL_FALSE</span> then <span class="c003">value</span> contains the input value of the argument with the same conventions as for input arguments (section <a href="#Input-arguments">10.3.4</a>). At the exit of the function, if unify is <span class="c003">PL_TRUE</span> <span class="c003">value</span> must contain the value to unify with the same conventions as for output arguments (section <a href="#Output-arguments">10.3.5</a>).</p><p>For instance, the effective argument <span class="c003">Arg</span> associated with <span class="c003">?positive</span> foreign declaration is handled as follows:</p><ul class="itemize"><li class="li-itemize">if <span class="c003">Arg</span> is a variable <span class="c003">is_var</span> and <span class="c003">unify</span> are set to <span class="c003">PL_TRUE</span> else to <span class="c003">PL_FALSE</span> and its value is copied in <span class="c003">value.l</span>.</li><li class="li-itemize">if <span class="c003">Arg</span> is neither a variable nor an integer a <span class="c003">type_error(integer, Arg)</span> is raised.</li><li class="li-itemize">if <span class="c003">Arg</span> is an integer < 0 a <span class="c003">domain_error(not_less_than_zero, Arg)</span> is raised.</li><li class="li-itemize">otherwise a pointer to the <span class="c003">PlFIOArg</span> (<span class="c003">PlFIOArg</span> <span class="c003">*</span>) is passed to the C function. If the function returns <span class="c003">PL_TRUE</span> and if <span class="c003">unify</span> is <span class="c003">PL_TRUE</span> the value stored in <span class="c003">value.l</span> is unified with <span class="c003">Arg</span>.</li></ul> <h4 class="subsubsection" id="sec344">10.3.7  Writing non-deterministic C code</h4> <p> <a id="Writing-non-deterministic-C-code"></a> The interface allows the user to write non-deterministic C code. When a C function is non-deterministic, a choice-point is created for this function. When a failure occurs, if all more recent non-deterministic code are finished, the function is re-invoked. It is then important to inform Prolog when there is no more solution (i.e. no more choice) for a non-deterministic code. So, when no more choices remains the function must remove the choice-point. The interface increments a counter each time the function is re-invoked. At the first call this counter is equal to 0. This information allows the function to detect its first call. When writing non-deterministic code, it is often useful to record data between consecutive re-invocations of the function. The interface maintains a buffer to record such an information. The size of this buffer is given by <a id="hevea_default1028"></a><span class="c003">choice_size(N)</span> when using <span class="c003">foreign/2</span> (section <a href="#foreign%2F2-directive">10.3.2</a>). This size is the number of (consecutive) <span class="c003">PlLong</span><em>s</em> needed by the C function. Inside the function it is possible to call the following functions/macros:</p><dl class="list"><dt class="dt-list"> </dt><dd class="dd-list"> <pre class="verbatim">int Pl_Get_Choice_Counter(void) TYPE Pl_Get_Choice_Buffer (TYPE) void Pl_No_More_Choice (void) </pre></dd></dl><p>The macro <span class="c003">Pl_Get_Choice_Counter()</span> returns the value of the invocation counter (0 at the first call).</p><p>The macro <span class="c003">Pl_Get_Choice_Buffer(<span class="c008">TYPE</span>)</span> returns a pointer to the buffer (casted to <span class="c004">TYPE</span>).</p><p>The function <span class="c003">Pl_No_More_Choice()</span> deletes the choice point associated with the function.</p> <h4 class="subsubsection" id="sec345">10.3.8  Example: input and output arguments</h4> <p> All examples presented here can be found in the <span class="c003">ExamplesC</span> sub-directory of the distribution, in the files <span class="c003">examp.pl</span> (Prolog part) and <span class="c003">examp_c.c</span> (C part).</p><p>Let us define a predicate <span class="c003">first_occurrence(A, C, P)</span> which unifies <span class="c003">P</span> with the position (from 0) of the first occurrence of the character <span class="c003">C</span> in the atom <span class="c003">A</span>. The predicate must fail if <span class="c003">C</span> does not appear in <span class="c003">A</span>.</p><p>In the prolog file <span class="c003">examp.pl</span>:</p><dl class="list"><dt class="dt-list"> </dt><dd class="dd-list"><span class="c003">:- foreign(first_occurrence(+string, +char, -positive)).</span></dd></dl><p>In the C file <span class="c003">examp_c.c</span>:</p><dl class="list"><dt class="dt-list"> </dt><dd class="dd-list"> <pre class="verbatim">#include <string.h> #include <gprolog.h> PlBool first_occurrence(char *str, PlLong c, PlLong *pos) { char *p; p = strchr(str, c); if (p == NULL) /* C does not appear in A */ return PL_FALSE; /* fail */ *pos = p - str; /* set the output argument */ return PL_TRUE; /* succeed */ } </pre></dd></dl><p>The compilation produces an executable called <span class="c003">examp</span>:</p><dl class="list"><dt class="dt-list"> </dt><dd class="dd-list"><span class="c003">% gplc examp.pl examp_c.c</span></dd></dl><p>Examples of use:</p><dl class="list"><dt class="dt-list"> </dt><dd class="dd-list"> <pre class="verbatim">| ?- first_occurrence(prolog, p, X). X = 0 | ?- first_occurrence(prolog, k, X). no | ?- first_occurrence(prolog, A, X). {exception: error(instantiation_error,first_occurrence/3)} | ?- first_occurrence(prolog, 1 ,X). {exception: error(type_error(character,1),first_occurrence/3)} </pre></dd></dl> <h4 class="subsubsection" id="sec346">10.3.9  Example: non-deterministic code</h4> <p> We here define a predicate <span class="c003">occurrence(A, C, P)</span> which unifies <span class="c003">P</span> with the position (from 0) of one occurrence of the character <span class="c003">C</span> in the atom <span class="c003">A</span>. The predicate will fail if <span class="c003">C</span> does not appear in <span class="c003">A</span>. The predicate is re-executable on backtracking. The information that must be recorded between two invocations of the function is the next starting position in <span class="c003">A</span> to search for <span class="c003">C</span>.</p><p>In the prolog file <span class="c003">examp.pl</span>:</p><dl class="list"><dt class="dt-list"> </dt><dd class="dd-list"><span class="c003">:- foreign(occurrence(+string, +char, -positive), [choice_size(1)]).</span></dd></dl><p>In the C file <span class="c003">examp_c.c</span>:</p><dl class="list"><dt class="dt-list"> </dt><dd class="dd-list"> <pre class="verbatim">#include <string.h> #include <gprolog.h> PlBool occurrence(char *str, PlLong c, PlLong *pos) { char **info_pos; char *p; info_pos = Pl_Get_Choice_Buffer(char **); /* recover the buffer */ if (Pl_Get_Choice_Counter() == 0) /* first invocation ? */ *info_pos = str; p = strchr(*info_pos, c); if (p == NULL) /* c does not appear */ { Pl_No_More_Choice(); /* remove choice-point */ return PL_FALSE; /* fail */ } *pos = p - str; /* set the output argument */ *info_pos = p + 1; /* update next starting pos */ return PL_TRUE; /* succeed */ } </pre></dd></dl><p>The compilation produces an executable called <span class="c003">examp</span>:</p><dl class="list"><dt class="dt-list"> </dt><dd class="dd-list"><span class="c003">% gplc examp.pl examp_c.c</span></dd></dl><p>Examples of use:</p><dl class="list"><dt class="dt-list"> </dt><dd class="dd-list"><table class="c001 cellpading0"><tr><td class="c015" colspan=3><span class="c003">| ?- occurrence(prolog, o, X).</span> </td></tr> <tr><td class="c015" colspan=3> </td></tr> <tr><td class="c015"><span class="c003">X = 2 ?</span></td><td class="c013">  </td><td class="c015">(here the user presses <span class="c003">;</span> to compute another solution)</td></tr> <tr><td class="c015" colspan=3> </td></tr> <tr><td class="c015"><span class="c003">X = 4 ?</span></td><td class="c013">  </td><td class="c015">(here the user presses <span class="c003">;</span> to compute another solution)</td></tr> <tr><td class="c015" colspan=3> </td></tr> <tr><td class="c015"><span class="c003">no</span></td><td class="c013">  </td><td class="c015">(no more solution)</td></tr> <tr><td class="c015" colspan=3> </td></tr> <tr><td class="c015" colspan=3><span class="c003">| ?- occurrence(prolog, k, X).</span> </td></tr> <tr><td class="c015" colspan=3> </td></tr> <tr><td class="c015" colspan=3><span class="c003">no</span> </td></tr> </table></dd></dl><p>In the first example when the second (the last) occurrence is found (<span class="c003">X=4</span>) the choice-point remains and the failure is detected only when another solution is requested (by pressing <span class="c003">;</span>). It is possible to improve this behavior by deleting the choice-point when there is no more occurrence. To do this it is necessary to do one search ahead. The information stored is the position of the next occurrence. Let us define such a behavior for the predicate <span class="c003">occurrence2/3</span>.</p><p>In the prolog file <span class="c003">examp.pl</span>:</p><dl class="list"><dt class="dt-list"> </dt><dd class="dd-list"><span class="c003">:- foreign(occurrence2(+string, +char, -positive), [choice_size(1)]).</span></dd></dl><p>In the C file <span class="c003">examp_c.c</span>:</p><dl class="list"><dt class="dt-list"> </dt><dd class="dd-list"> <pre class="verbatim">#include <string.h> #include <gprolog.h> PlBool occurrence2(char *str, PlLong c, PlLong *pos) { char **info_pos; char *p; info_pos = Pl_Get_Choice_Buffer(char **); /* recover the buffer */ if (Pl_Get_Choice_Counter() == 0) /* first invocation ? */ { p = strchr(str, c); if (p == NULL) /* C does not appear at all */ { Pl_No_More_Choice(); /* remove choice-point */ return PL_FALSE; /* fail */ } *info_pos = p; } /* info_pos = an occurrence */ *pos = *info_pos - str; /* set the output argument */ p = strchr(*info_pos + 1, c); if (p == NULL) /* no more occurrence */ Pl_No_More_Choice(); /* remove choice-point */ else *info_pos = p; /* else update next solution */ return PL_TRUE; /* succeed */ } </pre></dd></dl><p>Examples of use:</p><dl class="list"><dt class="dt-list"> </dt><dd class="dd-list"><table class="c001 cellpading0"><tr><td class="c015" colspan=3><span class="c003">| ?- occurrence2(prolog, l, X).</span> </td></tr> <tr><td class="c015" colspan=3> </td></tr> <tr><td class="c015"><span class="c003">X = 3</span></td><td class="c013">  </td><td class="c015">(here the user is not prompted since there is no more alternative)</td></tr> <tr><td class="c015" colspan=3> </td></tr> <tr><td class="c015" colspan=3><span class="c003">| ?- occurrence2(prolog, o, X).</span> </td></tr> <tr><td class="c015" colspan=3> </td></tr> <tr><td class="c015"><span class="c003">X = 2 ?</span></td><td class="c013">  </td><td class="c015">(here the user presses <span class="c003">;</span> to compute another solution)</td></tr> <tr><td class="c015" colspan=3> </td></tr> <tr><td class="c015"><span class="c003">X = 4</span></td><td class="c013">  </td><td class="c015">(here the user is not prompted since there is no more alternative)</td></tr> </table></dd></dl> <h4 class="subsubsection" id="sec347">10.3.10  Example: input/output arguments</h4> <p> We here define a predicate <span class="c003">char_ascii(Char, Code</span>) which converts in both directions the character <span class="c003">Char</span> and its character-code <span class="c003">Code</span>. This predicate is then similar to <a id="hevea_default1029"></a><span class="c003">char_code/2</span> (section <a href="gprolog043.html#char-code%2F2">8.19.4</a>).</p><p>In the prolog file <span class="c003">examp.pl</span>:</p><dl class="list"><dt class="dt-list"> </dt><dd class="dd-list"><span class="c003">:- foreign(char_ascii(?char, ?code)).</span></dd></dl><p>In the C file <span class="c003">examp_c.c</span>:</p><dl class="list"><dt class="dt-list"> </dt><dd class="dd-list"> <pre class="verbatim">#include <gprolog.h> PlBool char_ascii(PlFIOArg *c, PlFIOArg *ascii) { if (!c->is_var) /* Char is not a variable */ { ascii->unify = PL_TRUE; /* enforce unif. of Code */ ascii->value.l = c->value.l; /* set Code */ return PL_TRUE; /* succeed */ } if (ascii->is_var) /* Code is also a variable */ Pl_Err_Instantiation(); /* emit instantiation_error */ c->value.l = ascii->value.l; /* set Char */ return PL_TRUE; /* succeed */ } </pre></dd></dl><p>If <span class="c003">Char</span> is instantiated it is necessary to enforce the unification of <span class="c003">Code</span> since it could be instantiated. Recall that by default if an input/output argument is instantiated it will not be unified at the exit of the function (section <a href="#Input%2Foutput-arguments">10.3.6</a>). If both <span class="c003">Char</span> and <span class="c003">Code</span> are variables the function raises an <span class="c003">instantiation_error</span>. The way to raise Prolog errors is described later (section <a href="gprolog070.html#Raising-Prolog-errors">10.5</a>).</p><p>The compilation produces an executable called <span class="c003">examp</span>:</p><dl class="list"><dt class="dt-list"> </dt><dd class="dd-list"><span class="c003">% gplc examp.pl examp_c.c</span></dd></dl><p>Examples of use:</p><dl class="list"><dt class="dt-list"> </dt><dd class="dd-list"> <pre class="verbatim">| ?- char_ascii(a, X). X = 97 | ?- char_ascii(X, 65). X = 'A' | ?- char_ascii(a, 12). no | ?- char_ascii(X, X). {exception: error(instantiation_error,char_ascii/2)} | ?- char_ascii(1, 12). {exception: error(type_error(character,1),char_ascii/2)} </pre></dd></dl> <hr class="c011"> Copyright (C) 1999-2013 Daniel Diaz Verbatim copying and distribution of this entire article is permitted in any medium, provided this notice is preserved. <a href="index.html#copyright">More about the copyright</a> <hr> <a href="gprolog067.html"><img src="previous_motif.gif" alt="Previous"></a> <a href="gprolog065.html"><img src="contents_motif.gif" alt="Up"></a> <a href="gprolog069.html"><img src="next_motif.gif" alt="Next"></a> </body> </html>