Author(s): Jose Morales, Manuel Carro.
Version: 1.4 (1999/11/27, 19:0:0 MEST)
Version of last change: 1.3#123 (1999/11/27, 3:3:55 MET)
This module exports two predicates,
build_foreign_interface/1
and
rebuild_foreign_interface/1
. These predicates know about the correspondence between C types and Ciao Prolog types through the assertions documenting them.
Each predicate implemented as a foreign C function must appear in the module as:
:- true pred prolog_predicate(m1(Arg1), ... mN(ArgN)) :: type1 * ... * typeN + (foreign(foreign_function_name), returns(ArgR)). :- impl_defined([..., prolog_predicate/N, ...]).
where m1
, ..., mN
and type1
, ..., typeN
are respectively the modes and types of the arguments.
prolog_predicate/N
is implemented by foreign_function_name
, whose result is unified with ArgR
.
This notation can be simplified if the name of the foreign function is the same as the name of the Ciao Prolog predicate, replacing foreign(foreign_function)
with just foreign
. returns(ArgR)
specifies that the result of the function corresponds to the ArgR
argument of the Ciao Prolog predicate. If the foreign function does not return anything, then returns(ArgR)
must be removed. Note that returns
cannot be used without foreign
.
:- true pred prolog_predicate(m1(Arg1), ... mN(ArgN)) :: type1 * ... * typeN + foreign.
(This section has not been written yet)
The translation between Ciao Prolog and C types is defined only for some simple types. The translation to be performed is solely defined by types of the arguments in the Ciao Prolog predicate, obeying the table below:
Strings, atoms, and lists of bytes are passed to (and from) C as dynamically (malloc) created arrays of characters (bytes). Those arrays are freed by Ciao Prolog upon return of the foreign function unless
do_not_free/2
is specified (see examples below).
Empty lists of bytes are converted into NULL
, and strings []
or atoms " are converted into "" (a zero ended C string). NULL is converted into an empty list or the " atom.
NULL
strings and empty buffers are converted into the empty list or the null atom ("
). Empty Ciao Prolog strings ("
or []
) and null atoms are converted into zero-terminated strings of zero length. Empty Ciao Prolog lists are converted into NULL
.
The type
byte_list/1
requires an additional property,
size_of/3
, to indicate which argument represents its size.
math.pl
:- module(math, [sin/2, cos/2, fabs/2 ], [assertions, basicmodes, regtypes, 'foreign_interface/syntax' ]). :- true pred sin(in(X),go(Y)) :: num * num + (foreign,returns(Y)). :- true pred cos(in(X),go(Y)) :: num * num + (foreign,returns(Y)). :- true pred fabs(in(X),go(Y)) :: num * num + (foreign,returns(Y)). :- extra_compiler_opts(['-O2']). :- extra_compiler_opts('LINUXi86',['-ffast-math']). :- use_foreign_library([m]). :- impl_defined([sin/2,cos/2,fabs/2]).
objects.pl
:- module(objects, [object/2, show_object/1 ], [assertions, basicmodes, regtypes, 'foreign_interface/syntax' ]). :- true pred object(in(N),go(Object)) :: int * address + (foreign,returns(Object)). :- true pred show_object(in(Object)) :: address + foreign. :- use_foreign_source(objects_c). :- extra_compiler_opts('-O2'). :- impl_defined([object/2,show_object/1]).
objects_c.c
#include <stdio.h> struct object { char *name; char *colour; }; #define OBJECTS 3 struct object objects[OBJECTS] = { {"ring","golden"}, {"table","brown"}, {"bottle","green"} }; struct object *object(int n) { return &objects[n % OBJECTS]; } void show_object(struct object *o) { printf("I show you a %s %s\n", o->colour, o->name); }
byte_lists.pl
:- module(byte_lists, [obtain_list/3, show_list/2 ], [assertions, basicmodes, regtypes, 'foreign_interface/syntax' ]). :- true pred obtain_list(in(N),go(Length),go(List)) :: int * int * byte_list + (foreign,size_of(List,Length)). :- true pred show_list(in(Length),in(List)) :: int * byte_list + (foreign,size_of(List,Length)). :- use_foreign_source(bytes_op). :- impl_defined([obtain_list/3,show_list/2]).
bytes_op.c
#include <malloc.h> #include <stdio.h> void obtain_list(int n, int *l, char **s) { int i; int c; if (n < 0) n = 0; *l = n; *s = (char *)malloc(*l); for (i = 0; i < *l; i++) { (*s)[i] = i; } } void show_list(int l, char *s) { if (s) { int n; printf("From C: ["); for (n = 0; n < l; n++) { printf(" %d", s[n]); } printf("]\n"); } else { printf("From C: []\n"); } }
strings_and_atoms.pl
:- module(strings_and_atoms, [lookup_string/2, lookup_atom/2, a_string/1, show_string/1, show_atom/1 ], [assertions, basicmodes, regtypes, 'foreign_interface/syntax' ]). :- true pred a_string(go(S)) :: string + (foreign(get_static_str),returns(S),do_not_free(S)). :- true pred lookup_string(in(N),go(S)) :: int * string + (foreign(get_str),returns(S)). :- true pred lookup_atom(in(N),go(S)) :: int * atm + (foreign(get_str),returns(S)). :- true pred show_string(in(S)) :: string + foreign(put_str). :- true pred show_atom(in(S)) :: atm + foreign(put_str). :- use_foreign_source(str_op). :- impl_defined([lookup_string/2,lookup_atom/2,show_string/1,show_atom/1, a_string/1]).
str_op.c
#include <malloc.h> #include <stdio.h> char *get_static_str() { return "this is a string Ciao Prolog should not free"; } char *get_str(int n) { char *s; int size; int i; int c; if (n < 0) n = -n; size = (n%4) + 5; s = (char *)malloc(size+1); for (i = 0, c = ((i + n) % ('z' - 'a' + 1)) + 'a'; i < size; i++,c++) { if (c > 'z') c = 'a'; s[i] = c; } s[i] = 0; return s; } void put_str(char *s) { if (s) { printf("From C: \"%s\"\n", s); } else { printf("From C: null\n"); } }
foreign_interface
):- use_module(library(foreign_interface)).
foreign_interface
)
Usage: build_foreign_interface(in(File))
File
, generates the gluecode for the Ciao Prolog interface, compiles the foreign files and the gluecode file, and links everything in a shared object. Checks modification times to determine automatically which files must be generated/compiled/linked.
in(File)
is a source name.
(streams_basic:sourcename/1
)
Usage: rebuild_foreign_interface(in(File))
Usage: build_foreign_interface_explicit_decls(in(File),in(Decls))
Usage: build_foreign_interface_object(in(File))
in(File)
is a source name.
(streams_basic:sourcename/1
)
Usage: rebuild_foreign_interface_object(in(File))
in(File)
is a source name.
(streams_basic:sourcename/1
)
Usage: do_interface(in(Decls))
Decls
, this predicate succeeds if these declarations involve the creation of the foreign interface
in(Decls)
is a list of term
s.
(basic_props:list/2
)
Go to the first, previous, next, last section, table of contents.