Seed Modules

## Seed Modules Seed Modules — Native C modules for Seed |

## Synopsis

    #include <seed/seed.h>

    #define             CHECK_ARG_COUNT                     (name,
                                                             argnum)
    #define             DEFINE_ENUM_MEMBER                  (holder,
                                                             member)
    #define             DEFINE_ENUM_MEMBER_EXT              (holder,
                                                             name,
                                                             val)
    SeedObject          (*SeedModuleInitCallback)           (SeedEngine *eng);

## Description

Seed includes a simple system for creating C modules which can be loaded and manipulated from JavaScript. This is used for implementing performance-critical code closer to the silicon, as well as binding non-introspectable libraries in an attractive way.

Numerous binding modules are included in the Seed repository; when writing a new native module, it would be wise to look over these before beginning, as they have many tidbits of useful knowledge for writing modules.

Example 11. Very simple example C module

    #include <glib.h>
    #include <seed-module.h>
    SeedObject seed_module_init(SeedEngine * eng)
    {
        /* Say hello! */
        g_print("Hello, Seed Module World!\n");

        /* Return an empty object as the module's namespace */
        return seed_make_object (eng->context, NULL, NULL);
    }

Above is a C module which does absolutely nothing useful. When a module is loaded, `seed_module_init()` is called, which should have the signature of `SeedModuleInitCallback()`. You're passed the global SeedEngine, and the value you return is the namespace for your module. Say, for example, you place a static function on that object:

Example 12. C module with a function

    #include <glib.h>
    #include <seed-module.h>
    /* Our function, with the signature of SeedFunctionCallback(); say hello! */
    SeedValue say_hello_to(SeedContext ctx,
                           SeedObject function,
                           SeedObject this_object,
                           gsize argument_count,
                           const SeedValue arguments[],
                           SeedException *exception)
    {
        guchar * name;

        /* Check that only one argument was passed into the function.
           CHECK_ARG_COUNT() is from seed-module.h, which you might find useful. */
        CHECK_ARG_COUNT("hello.say_hello_to", 1);

        /* Convert the first argument, a SeedValue, to a C string */
        name = seed_value_to_string(ctx, arguments[0], exception);

        g_print("Hello, %s!\n", name);

        g_free(name);

        return seed_make_null(ctx);
    }

    /* Define an array of seed_static_function */
    seed_static_function gettext_funcs[] = {
        {"say_hello_to", say_hello_to, 0}
    };

    SeedObject seed_module_init(SeedEngine * eng)
    {
        SeedGlobalContext ctx = eng->context;

        /* Create a new class definition with our array of static functions */
        seed_class_definition ns_class_def = seed_empty_class;
        ns_class_def.static_functions = example_funcs;

        /* Create a class from the class definition we just created */
        SeedClass ns_class = seed_create_class(&ns_class_def);

        /* Instantiate the class; this instance will be the namespace we return */
        ns_ref = seed_make_object (ctx, ns_class, NULL);
        seed_value_protect (ctx, ns_ref);

        return ns_ref;
    }

After building and installing this module (look in the Seed build system for examples of how to get this to work, as well as a copy of seed-module.h, which will be very useful), it will be loadable with the normal Seed import system. Assuming it's installed as libseed_hello.so:

Example 13. Utilize our second example C module from JavaScript

    hello = imports.hello;
    hello.say_hello_to("Tim");

## Details

### CHECK_ARG_COUNT()

    #define             CHECK_ARG_COUNT(name, argnum)

Check that the required number of arguments were passed into a SeedFunctionCallback. If this is not true, raise an exception and return `NULL`. This requires the callback to use "argument_count", "ctx", and "exception" as the names of the various function arguments.

`name` should be of form "namespace.function_name"

At the moment, there is no way to specify more than one acceptable argument count.

`name` : | The name of the function being called from, pretty-printed
`argnum` : | The number of arguments which should be passed into the function

### DEFINE_ENUM_MEMBER()

    #define             DEFINE_ENUM_MEMBER(holder, member)

Defines a property on `holder` which is named the same as `member`, and is assigned the value that `member` has in C.

This macro works for defining properties from constants and #defines as well.

`holder` : | The object on which to define the enum member
`member` : | The enum member, as it is named in C

### DEFINE_ENUM_MEMBER_EXT()

    #define             DEFINE_ENUM_MEMBER_EXT(holder, name, val)

Defines a property on `holder` which is named `name`, and is assigned the value that `member` has in C. This allows for an override of the enum member's name, most often to remove a common prefix. For example, to declare a property named VERSION_MAJOR on the namespace from mfpr's version constant MPFR_VERSION_MAJOR:

    DEFINE_ENUM_MEMBER_EXT(ns, "VERSION_MAJOR", MPFR_VERSION_MAJOR);

`holder` : | The object on which to define the enum member
`name` : | The enum member, as it should be named in JavaScript
`val` : | The enum member, as it is named in C

### SeedModuleInitCallback ()

    SeedObject          (*SeedModuleInitCallback)           (SeedEngine *eng);