7.3.13. C Integration: Shared Modules
This tutorial demonstrates the module X shared mechanism and how it
solves a common integration problem: making a daslang module available
across independent compilations without requiring every das_file_access
to carry the module’s source file.
7.3.13.1. The problem
When you introduce a module file via das_fileaccess_introduce_file,
it is only visible to compilations that use that das_file_access.
A second file access (or a script in a different directory) cannot find
the file and fails with missing prerequisite; file not found:
// FileAccess #1 — both files present, works fine
das_file_access * fa1 = das_fileaccess_make_default();
das_fileaccess_introduce_file(fa1, "my_helpers.das", MODULE_SRC, 0);
das_fileaccess_introduce_file(fa1, "user_script.das", SCRIPT_SRC, 0);
das_program * p1 = das_program_compile("user_script.das", fa1, tout, libgrp);
// --> 0 errors
// FileAccess #2 — module file missing, fails
das_file_access * fa2 = das_fileaccess_make_default();
das_fileaccess_introduce_file(fa2, "user_script.das", SCRIPT_SRC, 0);
das_program * p2 = das_program_compile("user_script.das", fa2, tout, libgrp);
// --> error[30901]: missing prerequisite 'my_helpers'; file not found
7.3.13.2. The solution — module X shared
Add the shared keyword to the module declaration:
options gen2
module my_helpers shared
[export]
def double_it(x : int) : int {
return x * 2
}
When the module is compiled as a dependency (via require), the
compiler promotes it to the global module registry. Subsequent
compilations find it there – no file needed.
The promotion is a compile-time mechanism. A minimal “loader” script triggers it:
options gen2
require my_helpers
7.3.13.2.1. How it works internally
The parser sees
module my_helpers sharedand setsprogram.promoteToBuiltin = true.During dependency compilation, the compiler calls
Module::promoteToBuiltin()which inserts the module into the global linked list (daScriptEnvironment::modules).Ownership is transferred away from the program – the promoted module survives even after the program is released.
Module::require()finds the promoted module on subsequent compilations without any file lookup.das_shutdown()callsModule::ClearSharedModules()to free all promoted modules.
7.3.13.3. The C host code
All daslang source is embedded as C string constants. Four scripts are used:
Script |
Purpose |
|---|---|
|
Helper module without |
|
Same module with |
|
Minimal |
|
Uses the module: calls |
7.3.13.3.1. Part 1 — demonstrating the problem
// 1a: Same FileAccess — both files present, compiles fine
das_fileaccess_introduce_file(fa, "my_helpers.das", MODULE_NOT_SHARED, 0);
das_fileaccess_introduce_file(fa, "user_script.das", USER_SCRIPT, 0);
das_program * program = das_program_compile("user_script.das", fa, tout, libgrp);
// 0 errors
// 1b: Fresh FileAccess — module file not introduced
das_fileaccess_introduce_file(fa2, "user_script.das", USER_SCRIPT, 0);
das_program * program2 = das_program_compile("user_script.das", fa2, tout, libgrp);
// error[30901]: missing prerequisite 'my_helpers'; file not found
7.3.13.3.2. Part 2 — the shared module solution
// 2a: Compile the loader — promotes my_helpers to the global registry
das_fileaccess_introduce_file(fa, "my_helpers.das", MODULE_SHARED, 0);
das_fileaccess_introduce_file(fa, "loader.das", LOADER_SCRIPT, 0);
das_program * loader = das_program_compile("loader.das", fa, tout, libgrp);
// Release everything — the promoted module survives
das_program_release(loader);
das_fileaccess_release(fa);
// 2b: Fresh FileAccess — only the user script, no module file
das_file_access * fa2 = das_fileaccess_make_default();
das_fileaccess_introduce_file(fa2, "user_script.das", USER_SCRIPT, 0);
das_program * program = das_program_compile("user_script.das", fa2, tout, libgrp);
// 0 errors — module found in the global registry!
After successful compilation, the host simulates and calls test()
to verify the shared module’s functions work.
7.3.13.4. Build & run
Build:
cmake --build build --config Release --target integration_c_13
Run:
bin/Release/integration_c_13
Expected output:
=== Part 1: The Problem -- non-shared module across FileAccess boundaries ===
Part 1a: same FileAccess -- compilation succeeded (0 errors)
Part 1b: different FileAccess, module file missing -- compilation failed (1 error):
error 0: error[30901]: missing prerequisite 'my_helpers'; file not found ...
=== Part 2: The Solution -- module my_helpers shared ===
Part 2a: loader compiled -- 'my_helpers' promoted to global module registry
Part 2b: different FileAccess, no module file -- compilation succeeded!
double_it(21) = 42
Hello from my_helpers, tutorial 13!
test() returned: 42
See also
Full source:
13_shared_module.c
Previous tutorial: C Integration: Mock ECS
Tutorial C Integration: Sandbox — das_fileaccess_introduce_file and filesystem locking
C API reference: C API Reference
daScriptC.h API header: include/daScript/daScriptC.h