8.3.3. C Integration: Binding C Types

This tutorial shows how to create a custom module in C and expose C types (enumerations, structures, aliases) to daslang so that scripts can use them as native types.

8.3.3.1. Creating a module

A module is a named container for types and functions. The script refers to it with require:

das_module * mod = das_module_create("tutorial_c_03");

The module must be registered before compiling any script that requires it. After das_initialize(), call your registration function before das_program_compile.

8.3.3.2. Binding an enumeration

// C enum
typedef enum { Color_red = 0, Color_green = 1, Color_blue = 2 } Color;

// Bind to daslang
das_enumeration * en = das_enumeration_make("Color", "Color", 1);
das_enumeration_add_value(en, "red",   "Color_red",   Color_red);
das_enumeration_add_value(en, "green", "Color_green", Color_green);
das_enumeration_add_value(en, "blue",  "Color_blue",  Color_blue);
das_module_bind_enumeration(mod, en);

The third argument to das_enumeration_make is ext (boolean): non-zero means the enum’s underlying storage is int64; zero (the common case) means int. The example above passes 1, so Color is int64-backed — pass 0 for the usual int storage.

In daslang:

let color = Color.green
print("color = {color}\n")

8.3.3.3. Binding a structure

C structures are exposed as handled types. You specify size, alignment, and each field’s offset and mangled type:

typedef struct { float x; float y; } Point2D;

das_structure * st = das_structure_make(lib, "Point2D", "Point2D",
                                       sizeof(Point2D), _Alignof(Point2D));
das_structure_add_field(st, mod, lib, "x", "x", offsetof(Point2D, x), "f");
das_structure_add_field(st, mod, lib, "y", "y", offsetof(Point2D, y), "f");
das_module_bind_structure(mod, st);

In daslang:

var p : Point2D
p.x = 3.0
p.y = 4.0

8.3.3.4. Type mangling reference

Every type in the C API is described by a compact string:

Mangled string

Type

i

int

u

uint

f

float

d

double

b

bool

s

string

v

void

1<i>A

array<int>

1<f>?

float? (pointer)

H<Name>

handled struct Name

See Type Mangling for the complete specification.

8.3.3.5. Binding a type alias

das_module_bind_alias(mod, lib, "IntArray", "1<i>A");

In daslang, IntArray is now a synonym for array<int>.

8.3.3.6. Binding interop functions

Functions that operate on custom types use the standard interop pattern, but their mangled signatures reference the handled type by name:

// def point_distance(p : Point2D) : float
// Mangled: "f H<Point2D>"
vec4f c_point_distance(das_context * ctx, das_node * node, vec4f * args) {
    Point2D * p = (Point2D *)das_argument_ptr(args[0]);
    float dist = sqrtf(p->x * p->x + p->y * p->y);
    return das_result_float(dist);
}

das_module_bind_interop_function(mod, lib, &c_point_distance,
    "point_distance", "c_point_distance",
    SIDEEFFECTS_none, "f H<Point2D>");

Note the use of das_argument_ptr — structures are passed as pointers.

8.3.3.7. Building and running

cmake --build build --config Release --target integration_c_03
bin\Release\integration_c_03.exe

Expected output:

color = green
numbers = [ 10, 20, 30]
point = (3, 4)
distance from origin = 5
as string: (3.00, 4.00)

See also

Full source: 03_binding_types.c, 03_binding_types.das

Previous tutorial: C Integration: Calling daslang Functions

Next tutorial: C Integration: Callbacks and Closures

Type Mangling — complete type mangling reference