/ CData

Cdata is the Jsi interface used to generate C-API code for:

  • Struct and enum definitions
  • C-extensions using structs for state and options
  • Struct map/array variables

This is different from, but related to, JS Cdata

Definitions in .jsc files are preprocessed with jsish -c. The resulting .h output file contains compile-ready code.


Structs and enums are defined in jsc as follows:

enum BeeType = {

struct Bee = {
    int max;
    int buzzCnt;
    int stingCnt;
    int pollinateCnt;
    BeeType type;
    STRING32 flower;

The available struct field types are:

bool int8_t int16_t int32_t int64_t uint8_t uint16_t
uint32_t uint64_t float double ldouble Jsi_Strbuf time_w time_d time_t size_t 
intptr_t uintptr_t Jsi_Number int uint long ulong short ushort Jsi_Value* 
Jsi_DString Jsi_Value* Jsi_Value* Jsi_Value* Jsi_Value* Jsi_Value* Jsi_Value* Jsi_Value* 
Jsi_Strkey "const char*" 

Also supported are char arrays and STRING2, STRING4, ...: jsi.h has STRINGn typedefs for powers of 2 up to 64k.

All other types will be ignored or, like void *, are used for custom types.


There are two types of extension-commands in Jsi:
Name Description
ObjectObject commands with constructors eg. new RegExp(/abc/)
Non-objectNon-object commands, eg. Interp.conf()

Here is an excerpt from the example c-demos/cdata/Bee.jsc:

vars MyVars = {
    Bee Bee_Data;

extension Bee = { // Extension to create Bee commands.

    function conf(options:object|string=void):any { // Function to configure Bee options
        /* C code. */

    function buzz(n1:number):number { // Buzz
        /* C-code. */
        Bee_Data.buzzCnt += n1;
        Jsi_Number n = Bee_Data.buzzCnt;

    function sting(victim:string, times:number):string { // Sting
        /* C-code. */
        char buf[BUFSIZ];
        Bee_Data.stingCnt += times;
        snprintf(buf, sizeof(buf), "stung %s %g times", victim, times);
        RETURN(buf); //:string

    function pollinate(flower:string='daisy', times:number=1):void { // Pollinate
        /* C-code. */
        Bee_Data.pollinateCnt += times;
        Jsi_Stzcpy(Bee_Data.flower, flower);
        RETURN(); //:undefined

Note how function types are employed to simplify the interface. Next we generate it with:

jsish -c -outFile Bee.h Bee.jsc

To compile as a standalone we can use:

gcc -o Bee -I../.. -x c Bee.h -lpthread -ldl -lm -lz -DCDATA_MAIN

Or compile as a shared library using:

gcc -o Bee.so -I../.. -x c Bee.h -fPIC -shared -lpthread -ldl -lm -lz -DCDATA_MAIN=1 -DCDATA_SHARED=1

And run it like so:

Bee.sting('dog', 2);
Bee.conf({type:'Worker', buzzCnt:3});

Other examples in c-demos/cdata are:


Parameters are unloaded into function-local vars based on their type (singular). Type Unions are currently unsupported and simply ignored.

Several function names are treated specially:

  • conf: is the configuration command.
  • a function with the same name as the object will be treated as an Object-Command.
  • a function with a trailing options:object supports per-command options (see Baker.jsc).

Also if you define a var with the same name, but ending with _Data (eg. Bee_Data above) you can access the state via Cdata.get() etc (non-object commands only).

Returned Value

To return a function values, the RETURN() statement is used on a line by itself. The function return type determines what actually gets returned. As with parameters, this must not be a Type Union.


The example in c-demos/cdata/demo0.jsc defines two struct Foo and Bar.

vars MyVars = {
    Bar     bar;        // Struct Bar.
    Foo     foo;        // Struct Foo.
    Foo     foos[10];   // Array of Foo structs.
    Foo     foos2[FooSize];// Array of Foo structs with enum size.
    Bar     barss[10];  // Array of Bar.

    Bar     bars{};     // Map-Tree with string-key.
    Bar     BN{0};      // Map-Tree with integer-key.
    Bar     Bs{@Fidx};   // Map-Tree with struct-key.
    Bar     Bs2{#};     // Map-Hash with string-key
    Bar     BN2{#0};    // Map-Hash with integer key.  
    Bar     Bs2a{#@Fidx};// Map-Hash with struct-key.

Three different types of var-structs are declared:

  • Simple structs
  • Fixed size arrays of structs, denoted by square brackets.
  • Maps of structs, denoted by curley braces.

For maps:

  • The map type defaults tree, but can be over-ridden to hash {#}.
  • The key type defaults to string, but can be over-ridden as integer {0} or struct {@Name}.

A map can readily store large quantities of data, while arrays are useful for database queries.

Examples in c-demos/cdata using vars are:



If the first field of a struct has the name sig, it will be treated as a signature. This is a special integer value used to identify the struct. If not given a value, it will be a crc32 value calculated against the struct definition string without its field names and comments.

Signatures play a special role in data sent over the network.

Jsc Definitions

Each definition in a .jsc file ends with a single close curley brace + semicolon at the start of line.