Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ jobs:
cmake --no-warn-unused-cli -B./build -DCMAKE_BUILD_TYPE:STRING=${{ matrix.cmake_preset }} \
-G "${{ matrix.cmake_generator }}" $ACTIVE_MODULES
cd build
ninja daslang daslang_dyn
ninja daslang daslang_static
;;
*)
export CXXFLAGS="-Wno-elaborated-enum-base" # glfw module fails due to mac-os includes
Expand All @@ -217,7 +217,7 @@ jobs:
-G "${{ matrix.cmake_generator }}" $ACTIVE_MODULES

cd build
ninja daslang daslang_dyn
ninja daslang daslang_static
;;
esac
;;
Expand All @@ -234,8 +234,7 @@ jobs:
cmake)
cmake --no-warn-unused-cli -B./build -G "${{ matrix.cmake_generator }}" -T host=${{ matrix.architecture == 32 && 'x86' || 'x64' }} -A ${{ matrix.architecture_string }} \
$ACTIVE_MODULES -DCMAKE_TOOLCHAIN_FILE="$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake"
cmake --build ./build --config ${{ matrix.cmake_preset }} --target daslang
cmake --build ./build --config ${{ matrix.cmake_preset }} --target daslang_dyn
cmake --build ./build --config ${{ matrix.cmake_preset }} --target daslang --target daslang_static
;;
esac

Expand Down
37 changes: 36 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -284,8 +284,12 @@ SET(NEED_MODULES_PATH "${CMAKE_CURRENT_BINARY_DIR}/include")

SET(DAS_MODULES_RESOLVE_INC ${NEED_MODULES_PATH}/modules/external_resolve.inc)
SET(DAS_MODULES_NEED_INC ${NEED_MODULES_PATH}/modules/external_need.inc)
SET(DAS_MODULES_DECLARE_INC ${NEED_MODULES_PATH}/modules/external_declare.inc)
SET(DAS_MODULES_PULL_INC ${NEED_MODULES_PATH}/modules/external_pull.inc)
FILE(WRITE ${DAS_MODULES_RESOLVE_INC}.temp "")
FILE(WRITE ${DAS_MODULES_NEED_INC}.temp "")
FILE(WRITE ${DAS_MODULES_DECLARE_INC}.temp "")
FILE(WRITE ${DAS_MODULES_PULL_INC}.temp "")

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib)
Expand Down Expand Up @@ -381,6 +385,8 @@ ENDMACRO()

FUNCTION(ADD_MODULE_CPP cpp)
FILE(APPEND ${DAS_MODULES_NEED_INC}.temp "NEED_MODULE(Module_${cpp});\n")
FILE(APPEND ${DAS_MODULES_DECLARE_INC}.temp "DECLARE_MODULE(Module_${cpp});\n")
FILE(APPEND ${DAS_MODULES_PULL_INC}.temp "PULL_MODULE(Module_${cpp});\n")
ENDFUNCTION()

FUNCTION(ADD_MODULE_NATIVE native)
Expand Down Expand Up @@ -428,7 +434,21 @@ ADD_CUSTOM_COMMAND(
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${DAS_MODULES_RESOLVE_INC}.temp ${DAS_MODULES_RESOLVE_INC}
)

ADD_CUSTOM_TARGET(need_and_resolve ALL DEPENDS ${DAS_MODULES_NEED_INC} ${DAS_MODULES_RESOLVE_INC})
ADD_CUSTOM_COMMAND(
DEPENDS ${DAS_MODULES_DECLARE_INC}.temp
OUTPUT ${DAS_MODULES_DECLARE_INC}
VERBATIM
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${DAS_MODULES_DECLARE_INC}.temp ${DAS_MODULES_DECLARE_INC}
)

ADD_CUSTOM_COMMAND(
DEPENDS ${DAS_MODULES_PULL_INC}.temp
OUTPUT ${DAS_MODULES_PULL_INC}
VERBATIM
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${DAS_MODULES_PULL_INC}.temp ${DAS_MODULES_PULL_INC}
)

ADD_CUSTOM_TARGET(need_and_resolve ALL DEPENDS ${DAS_MODULES_NEED_INC} ${DAS_MODULES_RESOLVE_INC} ${DAS_MODULES_DECLARE_INC} ${DAS_MODULES_PULL_INC})

# libUriParser

Expand Down Expand Up @@ -923,6 +943,8 @@ endif()
SET(DAS_DASCRIPT_MAIN_SRC
${PROJECT_SOURCE_DIR}/utils/daScript/main.cpp
${DAS_MODULES_NEED_INC}
${DAS_MODULES_DECLARE_INC}
${DAS_MODULES_PULL_INC}
CACHE INTERNAL "DAS_DASCRIPT_MAIN_SRC"
)

Expand Down Expand Up @@ -1019,6 +1041,19 @@ get_target_property(DAS_FMT_LIBS das-fmt LINK_LIBRARIES)
# MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/utils/daScript/MacOSXBundleInfo.plist.in)
#ENDIF()

# Thread-safety test (issue #2027) — static link
add_executable(test_concurrent_init ${PROJECT_SOURCE_DIR}/tests/threading/test_concurrent_init.cpp)
TARGET_LINK_LIBRARIES(test_concurrent_init libDaScript ${SRC_LIBRARIES} ${DAS_MODULES_LIBS})
target_include_directories(test_concurrent_init PRIVATE ${NEED_MODULES_PATH})
SETUP_CPP11(test_concurrent_init)

# Thread-safety test (issue #2027) — dynamic link (DLL)
add_executable(test_concurrent_init_dyn ${PROJECT_SOURCE_DIR}/tests/threading/test_concurrent_init.cpp)
TARGET_LINK_LIBRARIES(test_concurrent_init_dyn libDaScriptDyn ${SRC_LIBRARIES})
ADD_DEPENDENCIES(test_concurrent_init_dyn libDaScriptDyn ${DAS_DYN_MODULES_LIBS})
target_include_directories(test_concurrent_init_dyn PRIVATE ${NEED_MODULES_PATH})
SETUP_CPP11(test_concurrent_init_dyn)

endif()

# This list should be significantly reduced, most of the files, except aot related should be private.
Expand Down
10 changes: 10 additions & 0 deletions doc/source/reference/embedding/cpp_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@ Derive from ``Module``, register bindings in the constructor, and use
The host uses ``NEED_MODULE(Module_MyMod)`` before ``Module::Initialize()``.
Scripts access it with ``require my_module_name``.

.. note::

``NEED_MODULE`` contains an ``extern`` declaration that binds to the
enclosing namespace. If your initialization code lives inside a C++
namespace, use the namespace-safe pair ``DECLARE_MODULE`` (file scope)
and ``PULL_MODULE`` (inside the namespace) instead. For external
modules, CMake also generates ``external_declare.inc`` and
``external_pull.inc`` alongside the traditional ``external_need.inc``.
See :ref:`tutorial_integration_cpp_namespace_integration`.

See :ref:`tutorial_integration_cpp_custom_modules` for a complete example.


Expand Down
1 change: 1 addition & 0 deletions doc/source/reference/tutorials.rst
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ and a companion ``.das`` script in ``tutorials/integration/cpp/``.
tutorials/integration_cpp_19_class_adapters.rst
tutorials/integration_cpp_20_standalone_contexts.rst
tutorials/integration_cpp_21_threading.rst
tutorials/integration_cpp_22_namespace_integration.rst

.. _tutorials_macros:

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
.. _tutorial_integration_cpp_namespace_integration:

.. index::
single: Tutorial; C++ Integration; Namespace Integration

==========================================
C++ Integration: Namespace Integration
==========================================

This tutorial shows how to initialize daslang modules when your code lives
inside a C++ namespace.

Topics covered:

* Why ``NEED_MODULE`` fails inside a namespace
* ``DECLARE_MODULE`` / ``PULL_MODULE`` — the namespace-safe alternative
* ``DECLARE_ALL_DEFAULT_MODULES`` / ``PULL_ALL_DEFAULT_MODULES``


Prerequisites
=============

* Tutorial 1 completed (:ref:`tutorial_integration_cpp_hello_world`) —
basic compile → simulate → eval cycle.


The problem
===========

The ``NEED_MODULE`` macro expands to an ``extern`` declaration followed
by a call:

.. code-block:: cpp

extern DAS_API das::Module * register_Module_BuiltIn();
*das::ModuleKarma += unsigned(intptr_t(register_Module_BuiltIn()));

When this macro is used inside a C++ namespace, the ``extern``
declaration is placed in that namespace's scope. The linker then looks
for ``MyApp::register_Module_BuiltIn()`` instead of the global
``::register_Module_BuiltIn()`` defined in the library:

.. code-block:: cpp

namespace MyApp {
void init() {
NEED_ALL_DEFAULT_MODULES; // FAILS: linker error!
das::Module::Initialize();
}
}

The solution is to split the declaration and the call into two separate
macros.


``DECLARE_MODULE`` / ``PULL_MODULE``
====================================

``DECLARE_MODULE(ClassName)`` — forward-declares the global-scope
``register_*`` function. Must be placed at file or global 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.

Convenience wrappers ``DECLARE_ALL_DEFAULT_MODULES`` and
``PULL_ALL_DEFAULT_MODULES`` cover every built-in module.


The tutorial
============

The tutorial runs the same ``01_hello_world.das`` script as Tutorial 1,
but all daslang calls happen inside ``namespace MyApp``.

.. literalinclude:: ../../../../tutorials/integration/cpp/22_namespace_integration.cpp
:language: cpp
:caption: tutorials/integration/cpp/22_namespace_integration.cpp


How it works
============

1. ``DECLARE_ALL_DEFAULT_MODULES`` at file scope forward-declares every
default module's ``register_*`` function as a global-scope symbol.

2. Inside ``MyApp::initialize()``, ``PULL_ALL_DEFAULT_MODULES`` calls
each ``::register_Module_*()`` function — the ``::`` prefix bypasses
the enclosing namespace.

3. ``Module::Initialize()`` and the rest of the daslang API continue to
work normally inside the namespace — only module registration has the
namespace restriction.


Custom modules
==============

For custom modules, use ``DECLARE_MODULE`` at file scope alongside the
convenience macros:

.. code-block:: cpp

DECLARE_ALL_DEFAULT_MODULES;
DECLARE_MODULE(Module_MyMod);

namespace MyApp {
void init() {
PULL_ALL_DEFAULT_MODULES;
PULL_MODULE(Module_MyMod);
das::Module::Initialize();
}
}


External (plugin) modules
=========================

CMake generates three ``.inc`` files for every module registered with
``ADD_MODULE_CPP``:

``external_need.inc``
Contains ``NEED_MODULE(...)`` — the traditional all-in-one macro
(works only at global scope).

``external_declare.inc``
Contains ``DECLARE_MODULE(...)`` — include at file scope.

``external_pull.inc``
Contains ``PULL_MODULE(...)`` — include inside any namespace or
function body.

For namespace-safe code, replace:

.. code-block:: cpp

// old (global scope only)
#include "modules/external_need.inc"

with:

.. code-block:: cpp

// file scope
#include "modules/external_declare.inc"

namespace MyApp {
void init() {
// inside namespace
#include "modules/external_pull.inc"
}
}


Build and run
=============

.. code-block:: bash

cmake --build build --config Release --target integration_cpp_22

.. code-block::

$ bin/Release/integration_cpp_22
Hello, World!
50 changes: 50 additions & 0 deletions include/daScript/daScriptModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,53 @@ namespace das
NEED_MODULE(Module_DASBIND); \
NEED_MODULE(Module_Network);

// DECLARE_MODULE / PULL_MODULE — namespace-safe alternatives to NEED_MODULE.
//
// NEED_MODULE places an `extern` declaration at the current scope, which
// fails inside a C++ namespace (the linker looks for Namespace::register_…
// instead of the global-scope function).
//
// Use DECLARE_MODULE at global/file scope to forward-declare the register
// function, then PULL_MODULE inside any namespace or function body to call it.
//
// Example:
// DECLARE_ALL_DEFAULT_MODULES; // file scope
// namespace MyApp {
// void init() {
// PULL_ALL_DEFAULT_MODULES; // OK — works inside namespace
// das::Module::Initialize();
// }
// }

#define DECLARE_MODULE(ClassName) \
extern DAS_API das::Module * register_##ClassName ()

#define PULL_MODULE(ClassName) \
*das::ModuleKarma += unsigned(intptr_t(::register_##ClassName()))

#define DECLARE_ALL_DEFAULT_MODULES \
DECLARE_MODULE(Module_BuiltIn); \
DECLARE_MODULE(Module_Math); \
DECLARE_MODULE(Module_Raster); \
DECLARE_MODULE(Module_Strings); \
DECLARE_MODULE(Module_Rtti); \
DECLARE_MODULE(Module_Ast); \
DECLARE_MODULE(Module_Debugger); \
DECLARE_MODULE(Module_Jit); \
DECLARE_MODULE(Module_FIO); \
DECLARE_MODULE(Module_DASBIND); \
DECLARE_MODULE(Module_Network)

#define PULL_ALL_DEFAULT_MODULES \
PULL_MODULE(Module_BuiltIn); \
PULL_MODULE(Module_Math); \
PULL_MODULE(Module_Raster); \
PULL_MODULE(Module_Strings); \
PULL_MODULE(Module_Rtti); \
PULL_MODULE(Module_Ast); \
PULL_MODULE(Module_Debugger); \
PULL_MODULE(Module_Jit); \
PULL_MODULE(Module_FIO); \
PULL_MODULE(Module_DASBIND); \
PULL_MODULE(Module_Network)

10 changes: 10 additions & 0 deletions modules/dasClangBind/.das_module
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
options gen2
require fio

[export]
def initialize(project_path : string) {
if (das_is_dll_build()) {
register_dynamic_module("{project_path}/dasModuleClangBind.shared_module", "Module_dasClangBind")
}
register_native_path("cbind", "cbind_boost", "{project_path}/cbind/cbind_boost.das")
}
6 changes: 5 additions & 1 deletion modules/dasClangBind/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,17 @@ IF ((NOT DAS_CLANG_BIND_INCLUDED) AND (${Clang_FOUND}) AND ((NOT ${DAS_CLANG_BIN

ADD_MODULE_CPP(dasClangBind)
# ADD_MODULE_NATIVE(CLANG_BIND_boost)
ADD_DAS_STATIC_MODULE_LIB(libDasModuleClangBind cbind_mod ${DAS_CLANG_BIND_MODULE_SRC} ${DAS_CLANG_BIND_MODULE_PLATFORM_SRC})
ADD_MODULE_LIB(libDasModuleClangBind dasModuleClangBind ${DAS_CLANG_BIND_MODULE_SRC} ${DAS_CLANG_BIND_MODULE_PLATFORM_SRC})
IF(APPLE)
TARGET_LINK_LIBRARIES(libDasModuleClangBind PRIVATE ${CLANG_BIND_LIBRARIES} ${LIBCLANG_LIB}/libclang.dylib)
TARGET_LINK_LIBRARIES(dasModuleClangBind PRIVATE ${CLANG_BIND_LIBRARIES} ${LIBCLANG_LIB}/libclang.dylib)
ELSE()
TARGET_LINK_LIBRARIES(libDasModuleClangBind PRIVATE ${CLANG_BIND_LIBRARIES} libclang)
TARGET_LINK_LIBRARIES(dasModuleClangBind PRIVATE ${CLANG_BIND_LIBRARIES} libclang)
ENDIF()
# ADD_DEPENDENCIES(libDasModuleClangBind)
TARGET_INCLUDE_DIRECTORIES(libDasModuleClangBind PUBLIC ${CLANG_BIND_INCLUDE_DIR} ${CLANG_INCLUDE_DIRS} ${LLVM_INCLUDE_DIRS})
TARGET_INCLUDE_DIRECTORIES(dasModuleClangBind PUBLIC ${CLANG_BIND_INCLUDE_DIR} ${CLANG_INCLUDE_DIRS} ${LLVM_INCLUDE_DIRS})

IF(WIN32)
set(DAS_CLANG_DLLS
Expand All @@ -88,4 +91,5 @@ ENDIF()
ADD_MODULE_DAS(cbind cbind cbind_boost)

SETUP_CPP11(libDasModuleClangBind)
SETUP_CPP11(dasModuleClangBind)
ENDIF()
3 changes: 3 additions & 0 deletions modules/dasClangBind/src/dasClangBind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ bool Module_dasClangBind::initDependencies() {
initMain();
return true;
}

REGISTER_DYN_MODULE(Module_dasClangBind,Module_dasClangBind);

}
REGISTER_MODULE_IN_NAMESPACE(Module_dasClangBind,das);

2 changes: 1 addition & 1 deletion modules/dasHV
Submodule dasHV updated from a494ce to 6f4eb7
Loading