Go to the first, previous, next, last section, table of contents.


Foreign interface

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.

Equivalence between Ciao Prolog and C modes

(This section has not been written yet)

Equivalence between Ciao Prolog and C types

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.

Examples

Mathematical functions

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]).

Addresses and C pointers

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);
}

Lists of bytes and buffers

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

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");
  }
}

Usage and interface (foreign_interface)

Documentation on exports (foreign_interface)

PREDICATE: build_foreign_interface/1:

Usage: build_foreign_interface(in(File))

PREDICATE: rebuild_foreign_interface/1:

Usage: rebuild_foreign_interface(in(File))

PREDICATE: build_foreign_interface_explicit_decls/2:

Usage: build_foreign_interface_explicit_decls(in(File),in(Decls))

PREDICATE: build_foreign_interface_object/1:

Usage: build_foreign_interface_object(in(File))

PREDICATE: rebuild_foreign_interface_object/1:

Usage: rebuild_foreign_interface_object(in(File))

PREDICATE: do_interface/1:

Usage: do_interface(in(Decls))


Go to the first, previous, next, last section, table of contents.