Xen

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.