Modify mj_PLUGIN_LIB_INIT to support multiple plugins in the same compilation unit.

Previously on MSVC we used DllMain to register plugins, you cannot have multiple definitions of DllMain in a single unit so you would get errors if you tried to register two plugins. This modifies the implementation to insert a function pointer into the C runtime initialization instead.

PiperOrigin-RevId: 896612678
Change-Id: I07732147b955d741c836acff6da986db0e9b9eff
This commit is contained in:
Sam Haves
2026-04-08 11:34:33 -07:00
committed by Copybara-Service
parent 33fd2fe40e
commit f2461f9ce6
14 changed files with 60 additions and 53 deletions
+6 -10
View File
@@ -691,17 +691,13 @@ mjPLUGIN_LIB_INIT
.. code-block:: C
#define mjPLUGIN_LIB_INIT \
static void _mjplugin_dllmain(void); \
mjEXTERNC int __stdcall mjDLLMAIN(void* hinst, unsigned long reason, void* reserved) { \
if (reason == 1) { \
_mjplugin_dllmain(); \
} \
return 1; \
} \
static void _mjplugin_dllmain(void)
#define mjPLUGIN_LIB_INIT(n) \
static void _mj_init_##n(void) __attribute__((constructor)); \
static void _mj_init_##n(void)
Register a plugin as a dynamic library. See :ref:`plugin registration<exRegistration>` for more details.
Register a plugin before `main()` is called. This macro takes a unique identifier `n` as an argument that is used to avoid
name collisions between different plugin initialization functions. See :ref:`plugin registration<exRegistration>` for
more details.
.. _tyXMacro:
+4
View File
@@ -44,6 +44,10 @@ General
- The ``vertcollide`` field in :ref:`mjsFlex` has been removed. It is no longer required since
:doc:`MuJoCo Warp <mjwarp/index>` supports native flex collisions.
- :ref:`mjPLUGIN_LIB_INIT` macro now requires a name argument to avoid initialization function name collisions.
When building with MSVC, we now use the C runtime initialization section to initialize plugins instead of
``DllMain``. See :ref:`plugin registration<exRegistration>` for more details.
- The :ref:`mjtWarning` enum value ``mjWARN_VGEOMFULL`` is removed. Exhaustion of visual geoms is now handled
internally by the :ref:`mjvScene`.
+5 -6
View File
@@ -230,12 +230,11 @@ troubleshoot issues with a model) can be statically linked into the application.
:ref:`mjpPlugin` struct in the ``main`` function, then passing it to :ref:`mjp_registerPlugin` to be registered with
MuJoCo.
Generally, reusable plugins are expected to be packaged as dynamic libraries. A dynamic library containing one or more
MuJoCo plugins should make sure that all plugins are registered when the library is loaded. In GCC-compatible compilers,
this can be achieved by calling :ref:`mjp_registerPlugin` in a function that is declared with
``__attribute__((constructor))``, while in MSVC this can be done in a DLL entry point (canonically known as
``DllMain``). MuJoCo provides a convenience macro :ref:`mjPLUGIN_LIB_INIT` that expands to either of these
constructs depending on the compiler used.
Generally, reusable plugins are expected to be packaged as libraries and should be registered when the library is
loaded. In GCC-compatible compilers, this can be achieved by calling :ref:`mjp_registerPlugin` in a function that is
declared with ``__attribute__((constructor))``, while in MSVC this can be done by injecting code into the C runtime
initialization. MuJoCo provides a convenience macro :ref:`mjPLUGIN_LIB_INIT` that expands to either of these constructs
depending on the compiler used.
Users of plugins that are delivered as dynamic libraries as described above can load the library using the function
:ref:`mj_loadPluginLibrary`. This is the preferred way to load dynamic libraries containing MuJoCo plugins (rather than,