Calling C language libraries

 

Syntax:

result = c(library,label[,arg . . .])

 

Synopsis:

This function is provided to allow JavaScript programs to execute functions written in C, in a type-safe manner. The user must provide a pre-compiled dynamic shared library containing the required functions. These must be written in the fashion described below.

The "result" is the name of a variable to receive the result of the call (if any). The value returned by the callee is converted into a JavaScript object of the appropriate type and returned to the caller. A void result is returned as undefined and detected errors are returned as a null (with errno set appropriately).

The library argument is a string containing the name of the library (without "lib" or ".so"). The first time it is referenced, the library is loaded according the directory order used by the load() function for external JavaScript libraries. Thereafter, it is used only as an index to find the already loaded library. The label argument specifies the external name of the function or variable within the dynamic library. It is resolved only once, on the first call. Thereafter, the label is used only as an index to a pointer to the external function or variable.

The arg list is an optional list of arguments to the function being called. They are coerced into basic primitive data types shared by JavaScript and C. Therefore, this list may only contain strings, numbers, booleans and null.

Within the C library, each function accepts exactly two arguments: a null terminated string and a variable length array of 8-byte unions of all permitted primitive types. Each byte of the string contains a single character, identifying the type of the primitive data in the corresponding element of the array of unions. The length of this string is equivalent to the total number of elements and the first is always reserved for the return value. No value is ever returned on the stack, so each function should be proto-typed as:

void funcName (char* type, Parg* args);

Where "Parg" is a union so simple we don't even bother providing a header. For example:

union Parg { double flt; int s32; unsigned b32; char byt; char* str; };

The JSUS c() function sets each character in the "type" string to n (null), b (byte or boolean), s (string pointer, i (32-bit signed integer), u (32-bit unsigned integer) or f (64-bit IEEE floating point double). These characters, and their values, begin with the second element of each argument passed to the function. Typically, the external function returns one of the same types as its first element, both in the string and the array. A n (null) is returned to the JavaScript as undefined (and corresponds to void in C). On error, the function should return "e", with errno set to an appropriate value, such as EINVAL. The c() function then returns a null to the JavaScript program.

Special note: Strings can, of course, be encoded in JavaScript Object Notation (JSON) and can be easily processed with the builtin JSON object methods. This eliminates the need to pass C structures back and forth and is far more appropriate for JavaScript programs. If needed, integral values greater than 32 bits can be passed, either way, as 53-bit integers within an IEEE double, without any loss of precision.

 

See also:

Executing JavaScript libraries