In Visual C++ 2013, I'm trying to export a function from a 'plugin' project:
void registerFactories(FactoryRegister<BaseShape> & factoryRegister);
Which is compliled into a dynamic dll which will be linked at runtime by an 'application' project. First I define the function pointer type:
typedef void (*RegisterFactoriesType)(FactoryRegister<BaseShape> &);
Which is used as:
auto registerFactories = (RegisterFactoriesType)GetProcAddress(dll, "registerFactories");
if (!registerFactories) {
if (verbose) {
ofLogWarning("ofxPlugin") << "No factories for FactoryRegister<" << typeid(ModuleBaseType).name() << "> found in DLL " << path;
}
FreeLibrary(dll);
return false;
}
However, the GetProcAddress
returns NULL.
I can confirm that I can export C functions (using extern "C"
) and import them from the same DLL using GetProcAddress
, but I importing the C++ function fails. e.g. this works:
extern "C" {
OFXPLUGIN_EXPORT void testFunction(int shout);
}
then
auto testFunction = (TestFunction)GetProcAddress(dll, "testFunction");
if (testFunction) {
testFunction(5);
}
So my presumption is that I need to somehow consider the mangled name which is exported for registerFactories
. Since it needs to deal with C++ types, ideally I want to do this without export "C"
.
Here's what dumpbin.exe
sees:
Dump of file examplePlugin.dll
File Type: DLL
Section contains the following exports for examplePlugin.dll
00000000 characteristics
558A441E time date stamp Wed Jun 24 14:46:06 2015
0.00 version
1 ordinal base
2 number of functions
2 number of names
ordinal hint RVA name
1 0 001B54E0 ?registerFactories@@YAXAEAV?$FactoryRegister@VBaseShape@@@ofxPlugin@@@Z = ?registerFactories@@YAXAEAV?$FactoryRegister@VBaseShape@@@ofxPlugin@@@Z (void __cdecl registerFactories(class ofxPlugin::FactoryRegister<class BaseShape> &))
2 1 001B5520 testFunction = testFunction
Summary
86000 .data
8E000 .pdata
220000 .rdata
E000 .reloc
1000 .rsrc
65D000 .text
EDIT :
registerFactories
is not the name to give to GetProcAddress
. By manually copying the mangled name from bindump e.g.:
auto registerFactories = (RegisterFactoriesType)GetProcAddress(dll, "?registerFactories@@YAXPEAV?$FactoryRegister@VBaseShape@@@ofxPlugin@@@Z");
It works! Therefore many of the answers below are related to discovering this mangled name at runtime.
I would not start a hunt for the mangled name. It's compiler dependent (which means also version dependent) and even if it works it would be a fragile solution.
I would suggest to get the address of your RegisterFactoriesType in antother way.
Assuming you have, in your plugin, a C-Style init function (whose address is available via GetProcAddress) I would do this:
struct init_data_t
{
RegisterFactoriesType factory ;
... other members
} ;
then inside init (so inside the DLL)
void init(init_data_t *data)
{
init_data->factory = &dll_factory ;
}
Basically you ask the DLL to give you the address of the factory function. The dll code does not need GetProcAddr, it can use address of (&)