8.4.22. C++ Integration: Namespace Integration
This tutorial shows how to initialize daslang modules when your code lives inside a C++ namespace.
Topics covered:
Why module registration entry points use C linkage
Using
NEED_MODULEsafely inside a namespaceDECLARE_MODULE/PULL_MODULEfor separately compiled modules
8.4.22.1. Prerequisites
Tutorial 1 completed (C++ Integration: Hello World) — basic compile → simulate → eval cycle.
8.4.22.2. Global C-linkage entry points
REGISTER_MODULE exposes an unmangled global C entry point. For example,
REGISTER_MODULE(Module_BuiltIn) provides:
extern "C" das::Module * register_Module_BuiltIn();
The built-in declarations are provided by daScriptModule.h.
NEED_MODULE calls the global entry point explicitly, so it is safe inside
a namespace:
namespace MyApp {
void init() {
NEED_ALL_DEFAULT_MODULES;
das::Module::Initialize();
}
}
8.4.22.3. DECLARE_MODULE / PULL_MODULE
Separately compiled custom modules are not known to daScriptModule.h.
DECLARE_MODULE(ClassName) forward-declares their global C-linkage
register_* function. It must be placed at file scope, outside any
namespace.
PULL_MODULE(ClassName) — performs the registration call using the
:: prefix to explicitly reference the global-scope function. Safe
inside any namespace, class, or function body. Once a declaration is
visible, NEED_MODULE and PULL_MODULE have the same pull behavior.
Convenience wrappers DECLARE_ALL_DEFAULT_MODULES and
PULL_ALL_DEFAULT_MODULES remain available, although the built-in
declarations are already supplied by the header.
8.4.22.4. The tutorial
The tutorial runs the same 01_hello_world.das script as Tutorial 1,
but all daslang calls happen inside namespace MyApp.
// Tutorial 22 — Namespace Integration
//
// Demonstrates how to initialize daslang modules inside a C++ namespace.
//
// Built-in registration entry points are globally declared with C linkage, so
// NEED_ALL_DEFAULT_MODULES is safe inside a namespace. Separately compiled
// custom modules use the DECLARE_MODULE / PULL_MODULE macro pair:
// • DECLARE_MODULE — forward-declares the register function (must be at
// file/global scope so it refers to the global symbol)
// • PULL_MODULE — calls the register function using ::qualified name
// (safe inside any namespace, class, or function body)
//
// NEED_MODULE and PULL_MODULE both call the global C-linkage entry point.
#include "daScript/daScript.h"
using namespace das;
#define SCRIPT_NAME "/tutorials/integration/cpp/01_hello_world.das"
// Separately compiled external modules are declared at global/file scope:
// #include "modules/external_declare.inc"
// ------------------------------------------------------------------
// Everything below lives inside a namespace — PULL_MODULE works here.
// ------------------------------------------------------------------
namespace MyApp {
void runScript() {
TextPrinter tout;
ModuleGroup dummyLibGroup;
auto fAccess = make_smart<FsFileAccess>();
auto program = compileDaScript(getDasRoot() + SCRIPT_NAME,
fAccess, tout, dummyLibGroup);
if (program->failed()) {
tout << "Compilation failed:\n";
for (auto & err : program->errors) {
tout << reportError(err.at, err.what, err.extra, err.fixme, err.cerr);
}
return;
}
Context ctx(program->getContextStackSize());
if (!program->simulate(ctx, tout)) {
tout << "Simulation failed:\n";
for (auto & err : program->errors) {
tout << reportError(err.at, err.what, err.extra, err.fixme, err.cerr);
}
return;
}
auto fnTest = ctx.findFunction("test");
if (!fnTest) {
tout << "Function 'test' not found\n";
return;
}
ctx.evalWithCatch(fnTest, nullptr);
if (auto ex = ctx.getException()) {
tout << "Script exception: " << ex << "\n";
}
}
void initialize() {
// Built-ins are already globally declared by daScriptModule.h. The macro
// calls their ::register_Module_* C entry points explicitly.
NEED_ALL_DEFAULT_MODULES;
// For external (plugin) modules, include the generated file:
// #include "modules/external_pull.inc"
Module::Initialize();
}
void shutdown() {
Module::Shutdown();
}
} // namespace MyApp
// main() delegates to the namespaced functions.
int main(int, char * []) {
MyApp::initialize();
MyApp::runScript();
MyApp::shutdown();
return 0;
}
8.4.22.5. How it works
daScriptModule.hdeclares the default module entry points globally with C linkage.Inside
MyApp::initialize(),NEED_ALL_DEFAULT_MODULEScalls each::register_Module_*()function explicitly.Module::Initialize()and the rest of the daslang API work normally inside the namespace.
8.4.22.6. Custom modules
For a separately compiled custom module, declare it at file scope before pulling it from a function or namespace:
DECLARE_MODULE(Module_MyMod);
namespace MyApp {
void init() {
NEED_ALL_DEFAULT_MODULES;
PULL_MODULE(Module_MyMod);
das::Module::Initialize();
}
}
8.4.22.7. External (plugin) modules
CMake generates three .inc files for every module registered with
ADD_MODULE_CPP:
external_need.incContains
NEED_MODULE(...)calls. The corresponding declarations must already be visible.external_declare.incContains
DECLARE_MODULE(...)— include at file scope.external_pull.incContains
PULL_MODULE(...)— include inside any namespace or function body.
The explicit declaration/pull pair is recommended:
// file scope
#include "modules/external_declare.inc"
namespace MyApp {
void init() {
// inside namespace
#include "modules/external_pull.inc"
}
}
8.4.22.8. Build and run
cmake --build build --config Release --target integration_cpp_22
$ bin/Release/integration_cpp_22
Hello, World!