GetProcAddress 用于将修饰的 C++ 函数导入 C++
GetProcAddress for importing a decorated C++ function into C++
在 Visual C++ 2013 中,我正在尝试从 'plugin' 项目中导出函数:
void registerFactories(FactoryRegister<BaseShape> & factoryRegister);
它被编译成一个动态 dll,它将在运行时由一个 'application' 项目链接。首先我定义函数指针类型:
typedef void (*RegisterFactoriesType)(FactoryRegister<BaseShape> &);
用作:
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;
}
但是,GetProcAddress
returns NULL。
我可以确认我可以导出 C 函数(使用 extern "C"
)并使用 GetProcAddress
从同一个 DLL 导入它们,但是我导入 C++ 函数失败了。例如这有效:
extern "C" {
OFXPLUGIN_EXPORT void testFunction(int shout);
}
然后
auto testFunction = (TestFunction)GetProcAddress(dll, "testFunction");
if (testFunction) {
testFunction(5);
}
所以我的假设是我需要以某种方式考虑为 registerFactories
导出的损坏的名称。由于它需要处理 C++ 类型,理想情况下我想在没有 export "C"
.
的情况下执行此操作
这是 dumpbin.exe
看到的:
文件转储 examplePlugin.dll
文件类型: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
编辑:
registerFactories
不是给 GetProcAddress
的名字。通过从 bindump 中手动复制损坏的名称,例如:
auto registerFactories = (RegisterFactoriesType)GetProcAddress(dll, "?registerFactories@@YAXPEAV?$FactoryRegister@VBaseShape@@@ofxPlugin@@@Z");
有效!因此,下面的许多答案都与在运行时发现这个损坏的名称有关。
我不会开始寻找被破坏的名字。它依赖于编译器(这意味着也依赖于版本),即使它有效,它也是一个脆弱的解决方案。
我建议以另一种方式获取您的 RegisterFactoriesType 的地址。
假设您的插件中有一个 C 风格的初始化函数(其地址可通过 GetProcAddress 获得),我会这样做:
struct init_data_t
{
RegisterFactoriesType factory ;
... other members
} ;
然后在 init 内部(所以在 DLL 内部)
void init(init_data_t *data)
{
init_data->factory = &dll_factory ;
}
基本上你要求DLL给你工厂函数的地址。 dll代码不需要GetProcAddr,可以使用地址(&)
在 Visual C++ 2013 中,我正在尝试从 'plugin' 项目中导出函数:
void registerFactories(FactoryRegister<BaseShape> & factoryRegister);
它被编译成一个动态 dll,它将在运行时由一个 'application' 项目链接。首先我定义函数指针类型:
typedef void (*RegisterFactoriesType)(FactoryRegister<BaseShape> &);
用作:
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;
}
但是,GetProcAddress
returns NULL。
我可以确认我可以导出 C 函数(使用 extern "C"
)并使用 GetProcAddress
从同一个 DLL 导入它们,但是我导入 C++ 函数失败了。例如这有效:
extern "C" {
OFXPLUGIN_EXPORT void testFunction(int shout);
}
然后
auto testFunction = (TestFunction)GetProcAddress(dll, "testFunction");
if (testFunction) {
testFunction(5);
}
所以我的假设是我需要以某种方式考虑为 registerFactories
导出的损坏的名称。由于它需要处理 C++ 类型,理想情况下我想在没有 export "C"
.
这是 dumpbin.exe
看到的:
文件转储 examplePlugin.dll
文件类型: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
编辑:
registerFactories
不是给 GetProcAddress
的名字。通过从 bindump 中手动复制损坏的名称,例如:
auto registerFactories = (RegisterFactoriesType)GetProcAddress(dll, "?registerFactories@@YAXPEAV?$FactoryRegister@VBaseShape@@@ofxPlugin@@@Z");
有效!因此,下面的许多答案都与在运行时发现这个损坏的名称有关。
我不会开始寻找被破坏的名字。它依赖于编译器(这意味着也依赖于版本),即使它有效,它也是一个脆弱的解决方案。
我建议以另一种方式获取您的 RegisterFactoriesType 的地址。
假设您的插件中有一个 C 风格的初始化函数(其地址可通过 GetProcAddress 获得),我会这样做:
struct init_data_t
{
RegisterFactoriesType factory ;
... other members
} ;
然后在 init 内部(所以在 DLL 内部)
void init(init_data_t *data)
{
init_data->factory = &dll_factory ;
}
基本上你要求DLL给你工厂函数的地址。 dll代码不需要GetProcAddr,可以使用地址(&)