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