@@ -182,21 +182,36 @@ struct mjSDF_ {
182182};
183183typedef struct mjSDF_ mjSDF ;
184184
185- #if defined(__has_attribute ) && __has_attribute (constructor )
186- #define mjPLUGIN_LIB_INIT \
187- static void _mjplugin_init(void) __attribute__((constructor)); \
188- static void _mjplugin_init(void)
185+ #if defined(__GNUC__ ) || defined(__clang__ )
186+ // GCC and Clang (including clang-cl)
187+ #define mjPLUGIN_LIB_INIT (n ) \
188+ static void _mj_init_##n(void) __attribute__((constructor)); \
189+ static void _mj_init_##n(void)
189190#elif defined(_MSC_VER )
191+ #define m_STR (x ) #x
192+ #define m_XSTR (x ) m_STR(x)
193+
194+ // On x86, symbols are decorated with a leading underscore.
195+ // On x64, they are not.
196+ #ifdef _M_IX86
197+ #define LINKER_NAME "__mj_ptr_"
198+ #else
199+ #define LINKER_NAME "_mj_ptr_"
200+ #endif
201+
190202 #pragma section(".CRT$XCU", read)
191203
192- #define mjPLUGIN_LIB_INIT \
193- static void __cdecl _mj_init_##__COUNTER__(void); \
194- /* The 'used' attribute for the linker */ \
195- __declspec(allocate (".CRT$XCU" )) \
196- static void (__cdecl * _mj_ptr_ ##__COUNTER__ )(void ) = _mj_init_ ##__COUNTER__ ; \
197- /* This pragma prevents the linker from optimizing this specific pointer away */ \
198- __pragma (comment (linker , "/include:" "_mj_ptr_" #__COUNTER__ )) \
199- static void __cdecl _mj_init_ ##__COUNTER__ (void )
204+ #define mjPLUGIN_LIB_INIT (n ) \
205+ static void __cdecl _mj_init_##n(void); \
206+ /* We use extern "C" to prevent C++ name mangling */ \
207+ extern "C" __declspec(allocate(".CRT$XCU")) \
208+ void (__cdecl * _mj_ptr_##n)(void) = _mj_init_##n; \
209+ /* Force the linker to include the pointer symbol */ \
210+ __pragma (comment (linker , "/include:" LINKER_NAME #n )) \
211+ static void __cdecl _mj_init_##n(void)
212+
213+ #else
214+ #error "Unknown compiler: Plugin registration not supported."
200215#endif
201216
202217// function pointer type for mj_loadAllPluginLibraries callback
0 commit comments