Files
cground/libs
2026-01-02 20:53:07 +11:00
..
2026-01-02 20:53:07 +11:00
2026-01-02 20:53:07 +11:00

Ground Libraries

This repo folder details the process for creating libraries with Ground, as well as some core libraries that are preinstalled with Ground.

Building Libraries

Ground comes with the groundvm.h and groundext.h header files for interfacing with Ground. If you're building something that wraps Ground, use groundvm.h. If you're building something that Ground itself uses (a library), use groundext.h (it includes groundvm.h but also has some extlib-specific things).

You can build your library in C or C++, or whichever language you can convince to interop with C code.

Note: C++ Ground extlibs and CGround extlibs are not compatible. Update your code for CGround.

Making a Function for CGround

Create a function with the following signature:

GroundValue myFn(GroundScope* scope, List args) {}
  • GroundScope* scope: For now does nothing. Will do something when structs are added.
  • List args: A list of args.

The List struct and associated structures look like this:

    typedef enum GroundValueType {
        INT, DOUBLE, STRING, CHAR, BOOL, LIST, FUNCTION, CUSTOM, NONE
    } GroundValueType;

    typedef struct List {
        size_t size;
        struct GroundValue* values;
    } List;

    typedef struct GroundValue {
        GroundValueType type;
        union {
            int64_t intVal;
            double doubleVal;
            char* stringVal;
            char charVal;
            bool boolVal;
            List listVal;
            struct GroundFunction* fnVal;
            void* customVal;
        } data;
    } GroundValue;

Your function needs to return a GroundValue. This can easily be created with the groundCreateValue() function, used like this:

// TYPE is one of the enum values from the GroundValueType enum.
// CONTENT is the associated data type (char* for string, int64_t for int, etc, etc)
groundCreateValue(TYPE, content);

// Real use:
groundCreateValue(STRING, "dingus");
groundCreateValue(INT, 32);

Once you've created your functions, you can create a ground_init() function to let Ground know about your functions. Use the groundAddNativeFunction() function to add your functions to Ground.

If your function fails, print some debug stuff to the console and return groundCreateValue(NONE). Proper error handling will be added soon.


GroundValue say_hi(GroundScope* scope, List args) {
    char* greeting = "Hello, ";
    if (list.size < 1) {
        printf("Expecting an argument!");
        return groundCreateValue(NONE);
    } 
    if (list.values[0].type != STRING) {
        printf("Expecting a string");
        return groundCreateValue(NONE);
    }
    // Insert stupid memory stuff here
    return groundCreateValue(STRING, greeting);
}

// ground_init takes a GroundScope* so it can add your functions to Ground
void ground_init(GroundScope* scope) {
    // groundAddNativeFunction(scope, "namespace_FnName", name_of_function, RETURNTYPE, 
    //                         amountOfArgs, ARGTYPE, "argName", ARGTYPE, "argName", ...)
    groundAddNativeFunction(scope, "utility_SayHi", say_hi, STRING, 1, STRING, "name");
}

Notes

When naming your functions, give them a prefix namespace like in C. Use camelCase for the namespace and CamelCase for the function name.

Document your functions somewhere! We want to be able to use them!