8.3.15. C Integration: Static StbImage Module
This tutorial demonstrates how a C host statically links an additional native
module and registers it before daScript finalizes module dependencies. It uses
StbImage and Raster as a concrete end-to-end example: an embedded script creates
an RGBA image through stbimage_boost and resizes it through Raster.
The host also uses the explicit-length *_n C APIs throughout. These APIs map
directly to languages such as D, whose strings are pointer/length slices and do
not need to be null-terminated.
8.3.15.1. Why initialization is split
das_initialize() remains the convenient one-call API for hosts which only
need the built-in modules. A host with statically linked application modules
needs an insertion point between registering the built-ins and resolving module
dependencies:
das_initialize_modules();
register_Module_Raster();
register_Module_StbImage();
das_initialize_finalize();
The three phases are:
das_initialize_modules()registers daScript’s built-in modules.The host calls every statically linked
register_Module_*entry point.das_initialize_finalize()initializes the complete dependency graph.
Do not call das_initialize() as well: it performs phases 1 and 3 itself.
8.3.15.2. C module entry points
Module registration functions have C linkage and therefore expose undecorated symbol names. A C host declares only the opaque C API return type:
extern das_module * register_Module_Raster(void);
extern das_module * register_Module_StbImage(void);
The equivalent declarations in D use extern(C):
extern(C) das_module* register_Module_Raster();
extern(C) das_module* register_Module_StbImage();
The application must link libDasModuleStbImage. That library contains the
Raster, StbImage, and StbTrueType registration functions.
8.3.15.3. Native module versus its daslang wrapper
Calling register_Module_StbImage makes the native functions available to
the compiler. The higher-level stbimage/stbimage_boost.das wrapper is still
a source module and must be visible through the compilation’s
das_file_access:
static const char BOOST_MODULE[] = "stbimage/stbimage_boost";
das_file_access * files = das_fileaccess_make_default();
if (!das_fileaccess_introduce_native_module_n(
files, BOOST_MODULE, sizeof(BOOST_MODULE) - 1)) {
/* The SDK's StbImage source module was not found. */
}
This distinction is important:
register_Module_StbImageregisters the statically linked C++ module.das_fileaccess_introduce_native_module_nintroduces its installed daslang wrapper into this file access.
8.3.15.4. The embedded daslang script
The script creates a 2x2 four-channel image, resizes it to 1x1, and returns a value encoding the resulting dimensions and channel count:
options gen2
require stbimage/stbimage_boost
[export]
def main : int {
var image = make_image(2, 2, 4)
var resized <- image.resize(1, 1)
return resized.width * 100 + resized.height * 10 + resized.channels
}
make_image exercises the StbImage wrapper. Image.resize reaches the
native Raster resize implementation. The expected return value is 114.
8.3.15.5. Explicit-length source and names
The host passes every string as a pointer and a size_t length. No
strlen call and no narrowing to uint32_t is required:
static const char SCRIPT_NAME[] = "stbimage_from_c.das";
static const char SCRIPT_SOURCE[] =
"options gen2\n"
"require stbimage/stbimage_boost\n"
/* ... */;
das_fileaccess_introduce_file_n(
files,
SCRIPT_NAME, sizeof(SCRIPT_NAME) - 1,
SCRIPT_SOURCE, sizeof(SCRIPT_SOURCE) - 1,
0);
das_program * program = das_program_compile_n(
SCRIPT_NAME, sizeof(SCRIPT_NAME) - 1,
files, output, modules);
The same pattern is used for das_context_find_function_n. Existing
null-terminated APIs remain available for compatibility.
8.3.15.6. Calling the result
After compilation and simulation, the host locates and invokes the exported
main function through the regular C evaluation API:
static const char MAIN_FUNCTION[] = "main";
das_function * main_function = das_context_find_function_n(
context, MAIN_FUNCTION, sizeof(MAIN_FUNCTION) - 1);
vec4f result = das_context_eval_with_catch(context, main_function, NULL);
if (!das_context_get_exception(context)) {
int value = das_argument_int(result); /* 114 */
}
Release the context, program, file access, module group, and output writer
before calling das_shutdown().
8.3.15.7. Static CMake linkage
The in-tree tutorial links the static module before the static compiler library. CMake carries the module’s transitive runtime dependencies:
target_link_libraries(integration_c_15 PRIVATE
libDasModuleStbImage libDaScript Threads::Threads)
An installed SDK exposes the corresponding imported targets as
DAS::libDasModuleStbImage and DAS::libDaScript. The standalone tutorial
build enables this target when the SDK was installed with StbImage support.
8.3.15.8. Build & run
Build:
cmake --build build --config Release --target integration_c_15
Run from the project root:
bin/Release/integration_c_15
Expected output:
static StbImage integration succeeded: 114
See also
Full source:
15_static_stbimage.c
Previous tutorial: C Integration: Passing Arrays
C API reference: C API Reference
Native and shared module details: External Modules
daScriptC.h API header: include/daScript/daScriptC.h