I have a program in which statically links with several C ++ libraries that export several functions:
extern "C" { KSrvRequestHandler* CreateRequestHandler( const char* name ); bool DestroyRequestHandler( KSrvRequestHandler* handler ); const char** ListRequestHandlerTypes(); }
The main program then calls these functions using GetProcAddress / dlsym:
#ifdef WIN32 HINSTANCE hDll = GetModuleHandle( NULL ); mCreateHandler = GetProcAddress( hDll, createFuncName ); mDestroyHandler = GetProcAddress( hDll, destroyFuncName ); mGetHandlerTypes = GetProcAddress( hDll, listFuncName ); #else
So, the key here is that I call the function in my own main program using dynamic linking.
(Why I do this is beyond the scope of the question, but the short answer is: it is a plug-in architecture, but I have some standard plugins that are directly related to the main binary, but I still want to download them through the same plug-in loading interface. For example , for built-in plugins, I download them by passing the current executable as the source of the plugin interfaces.)
Here's the problem: the linker does not know that I will need these functions and will not bind them.
How to make these functions communicate? For dynamic lib, just export them. But for exe, even the exported dll function is removed by the linker.
I know that I can possibly force a link by forcing the main binary code to assign these function addresses to something or another similar hack. Is there a proper way to do this?
@UPDATE: So, I have a solution that works, but it is necessarily ugly inside. Still looking for a better way.
Therefore, I need to somehow define the characters that I need in the object that loads the built-in interfaces. I don't think there is a way to force the linker to refer to a character otherwise. For instance. I do not know how to build a library with a function that is always related to the fact that it looks necessary or not. This is entirely at the discretion of the link stage for the executable.
So, in the executable, I have a macro that defines the built-in interfaces that I need. Each built-in plugin has a prefix for all of its interface functions, so at the top of the file I do:
DEFINE_BUILT_IN_PLUGIN( PluginOne ) DEFINE_BUILT_IN_PLUGIN( PluginTwo )
This will force me to define the functions that I need. But the macro for this is so ugly that I am filled with feelings of anger and self-doubt (I removed trailing slashes from the macro for readability):
#define FORCE_UNDEFINED_SYMBOL(x) void* _fp_ ## x ## _fp =(void*)&x; if (((ptrv) _fp_ ## x ##_fp * ( rand() | 1 )) < 1 ) exit(0); #define DEFINE_BUILT_IN_PLUGIN( PREFIX ) extern "C" { KSrvRequestHandler* PREFIX ## CreateRequestHandler( const char* name ); bool PREFIX ## DestroyRequestHandler( KSrvRequestHandler* handler ); const char** PREFIX ## ListRequestHandlerTypes(); } class PREFIX ## HandlerInterfaceMagic { public: PREFIX ## HandlerInterfaceMagic() { FORCE_UNDEFINED_SYMBOL( PREFIX ## CreateRequestHandler ); FORCE_UNDEFINED_SYMBOL( PREFIX ## DestroyRequestHandler ); FORCE_UNDEFINED_SYMBOL( PREFIX ## ListRequestHandlerTypes ); } }; PREFIX ## HandlerInterfaceMagic PREFIX ## HandlerInterfaceMagicInstance;
Since the compiler is an optimizing genuis, in FORCE_UNDEFINED_SYMBOLS, I'm going to draw great conclusions to trick the compiler into binding the unreferenced function. This macro only works inside a function. So I have to create this dummy magic class. There must be a better way.
In any case, it works.