Next: External Predicates in C
Up: Managing Data and Memory
Previous: Referring to ECLiPSe terms
  Index
Subsections
It is possible to include any C or C++ data in an ECLiPSe term. To do this
it is wrapped into a handle to tell ECLiPSe that this is external data.
You also have to supply a method table, which is a set of functions
that are called when ECLiPSe wants to make common operations that it
assumes can be done on any data (eg. comparing, printing).
To create an ECLiPSe wrapper for a C/C++ object,
the function handle()
is used. It takes a pointer to any C or C++
data, and a pointer to a suitable method table (t_ext_type
structure)
and creates an ECLiPSe handle term which refers to them.
Method tables for the common case of arrays of char, long or double
are predefined. For example a handle for a double array is made like this
double my_array[5] = {1.1, 2.2, 3.3, 4.4, 5.5};
EC_word w = handle(&ec_xt_double_arr, my_array);
where ec_xt_double_arr
is a predefined method table for arrays of doubles.
To convert back from an ECLiPSe term is_handle()
is used.
The method table passed in indicates the sort of data you expect to get.
If the ECLiPSe handle contains the wrong sort, the function returns
TYPE_ERROR:
if ((EC_succeed == w.is_handle(&ec_xt_double_arr, &obj))
obj->my_method();
else
cerr << "unexpected type\n";
The method table
Apart from the predefined method tables ec_xt_double_arr,
ec_xt_long_arr and ec_xt_char_arr, new ones can easily be defined.
The address of the table is used as a type identifier, so when you
get an external object back from ECLiPSe you can check its type
to determine the kinds of operations you can do on it.
You can choose not to implement one or more of these functions, by
leaving a null pointer ((void*)0
) in its field.
typedef void *t_ext_ptr;
typedef struct {
void (*free) (t_ext_ptr obj);
t_ext_ptr (*copy) (t_ext_ptr obj);
void (*mark_dids) (t_ext_ptr obj);
int (*string_size)(t_ext_ptr obj, int quoted);
int (*to_string) (t_ext_ptr obj, char *buf, int quoted);
int (*equal) (t_ext_ptr obj1, t_ext_ptr obj2);
t_ext_ptr (*remote_copy)(t_ext_ptr obj);
EC_word (*get) (t_ext_ptr obj, int idx);
int (*set) (t_ext_ptr obj, int idx, EC_word data);
} t_ext_type;
- free(t_ext_ptr obj)
-
This is called by ECLiPSe if it loses a reference to the external
data. This could happen if the ECLiPSe execution were to fail
to a point before the external object was created, or if a
permanent copy was explicitly removed with built-ins like
setval/2,
erase/2
or bag_dissolve/2.
Note that an invocation of this function only means that one
reference has been deleted (while the copy function indicates that
a reference is added).
- copy(t_ext_ptr obj)
- This is called by ECLiPSe when it wants to make a copy of an object.
This happens when calling ECLiPSe built-ins like setval/2 or
recordz/2 which make permanent copies of data. The return value is
the copy.
If no copy-method is specified, these operations will not be possible
with terms that contain an object of this type.
A possible implementation is to return a pointer to the original and
e.g. increment a reference counter (and decrement the counter in
the free-method correspondingly).
- mark_dids( t_ext_ptr obj)
- This is called during dictionary garbage collection. If an external
object contains references to the dictionary (
dident
) then
it needs to mark these as referenced.
- string_size(t_ext_ptr obj, int quoted)
- to_string(t_ext_ptr obj,char *buf, int quoted)
- When ECLiPSe wants to print an external object it calls
string_size()
to get an estimate of how large the string would be that represents it.
This is used by ECLiPSe to allocate a buffer. The string representation must
be guaranteed to fit in the buffer.
Finally the to_string()
function is called. This should write the
string representation of the object into the buffer.
- equal(t_ext_ptr obj1, t_ext_ptr obj2)
- This is called when two external objects are unified or compared.
Prolog views the external object as a ground, atomic element.
- remote_copy(t_ext_ptr obj)
- This is called by parallel ECLiPSe when it needs to make a copy of an
object in another worker. If the object is in shared memory, this method
can be the same as the copy method.
- get(t_ext_ptr obj, int idx)
- Returns the value of a field of the C++ object.
This methods gets invoked when the ECLiPSe predicate xget/3 is called.
The mapping of index values to fields is defined by the get/set-method pair.
- set(t_ext_ptr obj, int idx, EC_word data)
- Set the value of a field of the C++ object.
This methods gets invoked when the ECLiPSe predicate xset/3 is called.
The mapping of index values to fields is defined by the get/set-method pair.
Example of the simplest possible user-defined method table:
t_ext_type my_type = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
my_struct data_in;
...
// creating a handle for data_in
EC_word w = handle(&my_type, &data_in);
...
// checking a handle and extracting the data pointer
my_struct *data_out;
if ((EC_succeed == w.is_handle(&my_type, &data_out))
data_out->my_method();
else
cerr << "unexpected type\n";
Next: External Predicates in C
Up: Managing Data and Memory
Previous: Referring to ECLiPSe terms
  Index
Warwick Harvey
2004-08-07