为什么我不能使用 GetProcAddress 在 DLL 中调用C++静态类工厂方法?
Why can't I call a C++ static class factory method in a DLL with GetProcAddress?
我正在尝试使用以下标头加载一个假设的插件:
#ifndef _DLL_H_
#define _DLL_H_
#if BUILDING_DLL
# define DLLIMPORT __declspec (dllexport)
#else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec (dllimport)
#endif /* Not BUILDING_DLL */
class DLLIMPORT DllClass
{
public:
virtual ~DllClass(void);
static DllClass* getPCFilter();
virtual int Process(int a, int b);
protected:
DllClass();
};
#endif /* _DLL_H_ */
我的主机代码确实:
HINSTANCE hinstDLL;
hinstDLL = LoadLibrary(L"PCFilter.dll");
if(hinstDLL)
{
typedef DllClass*(*Factory)();
Factory fun1;
fun1 = (Factory)GetProcAddress(hinstDLL, "DllClass::getPCFilter");
dll 将打开,但 GetProcAddress 找不到静态工厂方法。我不应该这样做吗?
我尝试摆脱静态方法,而是在类声明之后执行以下操作:
extern "C" DLLIMPORT void* getPCFilterInstance()
{
return (void*)new DllClass();
}
但是,在编译主机源时,链接器抱怨:
In function `getPCFilterInstance'::
[Linker Error] undefined reference to `_imp___ZN8DllClassC1Ev'
我可以通过链接到 .a 库来解决。但是 DLL 的想法不是在编译时不需要链接吗?
您忽略了以下事实:函数名称将被修饰("名称重整")或在 DLL 接口中根本不可见(在给定名称下)。据我所知,GetProcAddress
不执行任何名称拆解,但是链接器会这样做(当静态导入带有导出类的 DLL 时)。
据我所知,最佳做法是提供一个工厂函数,该函数具有未修饰的名称和预定义的调用约定,就像 COM 规定的那样(请参阅DllGetClassObject
)。
注意:我应该补充一点,根据所使用的编译器/链接器,装饰("残缺")名称会有所不同。不同的编译器,不同的规则。因此,如果没有大量的修补,它们甚至可能彼此不兼容。
编辑:关于这个问题:
但是 DLL 的想法不是在编译时不需要链接吗?
嗯,是也不是。在Windows上,整个过程与unixoid系统中的过程有些不同。加载程序将负责解析依赖项等,但关键是有两种加载 DLL 的方法。一种是通过静态导入 DLL,在这种情况下,名称解析在您的程序开始运行之前完成(或在此之前失败),另一种是通过 LoadLibrary
和朋友动态加载 DLL,然后使用 GetProcAddress
解析函数地址。后者有一个变体(由链接器支持),称为延迟加载。最终,它仍然只是第二种方法。
延迟加载可能完全提供您想要的内容,方法是让链接器关心要解析的名称,并且仍然能够在运行时处理加载 DLL 或解析名称的故障。
extern "C"
语句导出与在代码中声明的函数相同的名称 - 否则它将被C ++编译器破坏
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 函数调用中参数的顺序重要吗
- OpenGL - 在抛出"__gnu_cxx::recursive_init_error"实例后终止调用?
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在c++类上调用void函数
- 为什么 std::unique 不调用 std::sort?
- 调用专用模板时出错"no matching function for call to [...]"
- 选择要调用的构造函数
- C++为什么尽管我调用了void函数,它却不起作用
- 构造函数正在调用一个使用当前类类型的函数
- 变量没有改变?通过向量的函数调用
- 没有为自己的结构调用列表推回方法
- 调用'begin(int [n])'没有匹配函数
- 什么时候调用析构函数
- 如何用参数值调用函数(仅在运行时已知)
- std::cout.imbue()多重调用
- 函数何时会在c++中包含stack_Unwind_Resume调用