THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 23/05/2003 at 02:28, xxxxxxxx wrote:
Yes, this is a problem with all global memory allocations. The runtime allocates global objects before the C4DOS connection has been initialized.
This isn't official advice yet, but what I did in one of my own plugins that needed global objects was to modify the internal glue of the API in c4d_pmain.cpp.
You have to modify pmain.cpp like this:
// this is the "glue" to C4D...
// please modify only if you know exactly what you are doing...
#ifdef WIN32
#include <windows.h>
#endif
#include "c4d_plugin.h"
#ifdef __MAC
#ifdef __cplusplus
extern "C" {
#endif
extern void __sinit(void);
extern void __destroy_global_chain(void);
#define C4D_MAIN LONG c4d_main(LONG action, void* p1, void* p2, void* p3)
C4D_MAIN;
#ifdef __cplusplus
}
#endif
#else
#ifdef __PC
#ifdef __cplusplus
extern "C" {
#endif
#define C4D_MAIN LONG __declspec(dllexport) c4d_main(LONG action, void* p1, void* p2, void* p3)
C4D_MAIN;
/*BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
<remove>
}*/
extern BOOL APIENTRY _CRT_INIT(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved);
static HINSTANCE g_hinstDLL;
static LPVOID g_lpReserved;
BOOL APIENTRY DllMainCRTStartup( HINSTANCE hinst, DWORD reason, LPVOID reserved )
{
g_hinstDLL = hinst;
g_lpReserved = reserved;
return TRUE;
}
#ifdef __cplusplus
}
#endif
#else
#error "Unsupported OS"
#endif
#endif
LONG InitOS(void *p);
CHAR path_storage[1024];
C4D_MAIN //(LONG action, void* p1, void* p2, void* p3)
{
static LONG init_count = 0;
LONG i;
CHAR *c;
switch (action)
{
case C4DPL_INIT_VERSION:
return C4DPL_VERSION;
case C4DPL_INIT_SYS:
init_count += 1;
if (init_count == 1)
{
if (InitOS(p1) < 7500) return C4DPL_ERROR_VERSION;
#ifdef __PC
_CRT_INIT(g_hinstDLL, DLL_PROCESS_ATTACH, g_lpReserved);
#endif
#ifdef __MAC
__sinit();
#endif
if (!p3) return C4DPL_ERROR_VERSION;
for (i = 0, c = (CHAR* )p3; c[i]; i++) path_storage[i] = c[i];
path_storage[i] = 0;
}
return 1;
case C4DPL_MESSAGE:
if (!PluginMessage((LONG)p1,p2)) return C4DPL_ERROR;
return 1;
case C4DPL_INIT:
return PluginStart();
case C4DPL_END:
init_count -= 1;
if (init_count == 0)
{
PluginEnd();
void FreeResource();
FreeResource();
#ifdef __PC
_CRT_INIT(g_hinstDLL, DLL_PROCESS_DETACH, g_lpReserved);
#endif
#ifdef __MAC
__destroy_global_chain();
#endif
}
return 1;
default:
break;
}
return C4DPL_ERROR;
}
One also must add /ENTRY:DllMainCRTStartup to the linker options to make it link.
This way you defer the call to _CRT_INIT(), which allocates all globals, until after the C4DPL_INIT_SYS message.
Note: I have used and tested this myself, but there's no guarantee that it is 100 % safe, or that it will work with future versions. I'll remind the programmers to look into this again so that the above can perhaps be incorporated into official future versions.