用于将修饰的C++函数导入C++的GetProcAddress
GetProcAddress for importing a decorated C++ function into C++
在Visual C++2013中,我正试图从"插件"项目导出一个函数:
void registerFactories(FactoryRegister<BaseShape> & factoryRegister);
它被编译成一个动态dll,该dll将在运行时由"应用程序"项目链接。首先我定义了函数指针类型:
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
返回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风格的init函数(其地址可通过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,它可以使用(&)的地址
我不久前专门为此创建了一个库。这里有一个用法示例,我希望它能有所帮助。
相关文章:
- 尝试导入pybind-opencv模块时出现libgtk错误
- 导入库可以跨dll版本工作吗
- 建议在运行时将带有类实例的列表从c++导入qml
- 导入/导出变量时出错
- 为什么导入Mixed native/CLR lib.dll的本机C++应用程序没有在Mixed lib.dll中的外部变
- 将QT项目导入Visual Studio 2019会给我带来很多LNK2001错误
- 是否可以将函数导入命名空间,但不能导出它?
- 如何将 CLion C++ 项目导入 Visual Studio?
- Python 3.8 不能与 Pybind11 一起导入 [Windows]
- 无法将标准库导入本机 android 项目中的头文件
- 尝试了解在导入的静态方法上使用删除方法时的错误
- 在 python 模块中导入子模块时PyImport_Import失败
- 将 C# DLL 导入 C++ 以用于 JNI
- 使用 QSslCertificate 在 Qt 中正确导入 pkcs12
- 在从Qt调用的Python脚本中导入OpenCV崩溃
- 编译boost_python扩展无法在 python 2.7 中导入
- 如何在安卓工作室中将c ++头文件从一个文件夹导入到另一个文件夹?
- Dll在同一解决方案中从 c# 项目导入到 c++ 项目
- C++20 使用 Visual Studio 编译模块:不编译或导入 ixx 文件
- 我可以将cocos项目导入虚幻4吗?