The Xen package provides macros and procedures making it possible for the same C code to support several different embedded (or extension) languages. Currently supported are s7, Ruby, and Forth.
Here's a program that defines a function (named "fnc" in the extension language) that takes an integer argument and increments it, a variable (named "var" in the extension language) that is initialized to 32, a constant (named "twelve") that has the value 12, then places you in a read-eval-print loop:
#include <stdio.h> #include "xen.h" static XEN orig_function(XEN argument) { XEN_ASSERT_TYPE(XEN_INTEGER_P(argument), argument, XEN_ONLY_ARG, "fnc", "an integer"); fprintf(stdout, "argument is %d\n", XEN_TO_C_INT(argument)); return(C_TO_XEN_INT(XEN_TO_C_INT(argument) + 1)); } XEN_NARGIFY_1(function, orig_function); static XEN variable; int main(int argc, char **argv) { xen_initialize(); XEN_DEFINE_VARIABLE("var", variable, C_TO_XEN_INT(32)); XEN_DEFINE_CONSTANT("twelve", 12, "this is 12"); XEN_DEFINE_PROCEDURE("fnc", function, 1, 0, 0, "this is our function"); fprintf(stdout, "we're running: %s\n", xen_version()); xen_repl(argc, argv); return(0); }
The "XEN_ARGIFY" step is needed for those languages that assume one calling sequence for a C-defined function; we have to wrap up the actual call in whatever sequence the extension language wants.
Currently constants are assumed to be integers. Type checks are handled by macros such as XEN_INTEGER_P; type conversions by macros such as XEN_TO_C_INT or C_TO_XEN_INT.