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));
}
#ifdef XEN_ARGIFY_1
XEN_NARGIFY_1(function, orig_function);
#else
#define function orig_function
#endif
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.