Para ilustrar el enlace dinámico de funciones C con LE-LISP vamos a mostrar
un pequeño ejemplo, consistente en la creación de funciones en C que permitan
acceder a un programa escrito en LE-LISP a los campos de una estructura compleja
creada en C
.
El fichero def.h contiene la definición de las estructuras object_values y VALUE:
#include <stdio.h>
struct VALUE
{
int data_item;
VALUE *next_value;
};
struct object_values
{
VALUE * level,
temperature,
pressure;
},
En el fichero example.c se define una variable de tipo object_values llamada myvalues que almacena tres listas con los datos de nivel, temperatura y presión en varios instantes de tiempo. También se definen las funciones car_level, car_temperature y car_pressure que permiten obtener el primer valor de la lista de niveles, temperaturas y pressiones asociadas a un objeto de tipo object_values. La función initialize_values da valores a los campos de una variable de tipo object_values. Por simplicidad sólo crea el primer elemento de cada lista de valores.
#include <stdio.h>
#include <malloc.h>
#include "def.h"
struct object_values myvalues={NULL,NULL,NULL};
/* return the address of 'myvalues' */
struct object_value *
get_object()
{
return &myvalues;
}
/* Initialize the values of the object returned by 'get_object()' */
struct object_values *
initialize_values(a_object_value)
struct object_values * a_value_object;
{
struct VALUE *level;
struct VALUE *temperature;
struct VALUE *pressure;
/* initialize level */
level=malloc(sizeof(struct VALUE));
level->data_item=46;
level->next_value=NULL;
(a_object_value->level)=level;
/* initialize temperature */
temperature=malloc(sizeof(struct VALUE));
temperature->data_item=28;
temperature->next_value=NULL;
(a_object_value->temperature)=temperature;
/* initialize pressure */
pressure=malloc(sizeof(struct VALUE));
pressure->data_item=770;
pressure->next_value=NULL;
(a_object_value->pressure)=pressure;
/* return the initialized object */
return a_value_object;
}
/* return the first level of 'a_object_value' */
integer
car_level(a_object_value)
struct object_values a_object_value;
{
return (a_object_value->level)->data_item;
}
/* return the first temperature of 'a_object_value' */
integer
car_temperature(a_object_value)
struct object_values a_object_value;
{
return (a_object_value->temperature)->data_item;
}
/* return the first pressure of 'a_object_value' */
integer
car_pressure(a_object_value)
struct object_values a_object_value;
{
return (a_object_value->pressure)->data_item;
}
Mediante cc -c example.c obtenemos el fichero binario example.o con las funciones C compiladas.
En el fichero example.ll se crean mediante defextern los enlaces dinámicos a las funciones contenidas en example.o:
(cload "example.o") (defextern _get_object () t) (defextern _initialize_values (t) t) (defextern _car_level (t) fix) (defextern _car_temperature (t) fix) (defextern _car_pressure (t) fix) (setq myvalues (_initialize_values (_get_object))) (print "The level is : " (_car_level myvalues " %") (print "The temperature is: " (_car_temperature myvalues " celsius grades") (print "The pressure is : " (_car_pressure myvalues " mmHg")
Una vez dentro del sistema LE-LISP podemos ejcutar el programa example.ll para obtener la siguiente respuesta:
? ^Lexample.ll The level is : 46 % The temperature is: 28 celsius grades The pressure is : 770 mmHg