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:
then inside init (so inside the DLL)
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 (&)