[英]Why can't I call a C++ static class factory method in a DLL with GetProcAddress?
I'm trying to load a hypothetical plugin with the following header:我正在尝试使用以下 header 加载一个假设的插件:
#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_ */
And my host code does:我的主机代码是这样的:
HINSTANCE hinstDLL;
hinstDLL = LoadLibrary(L"PCFilter.dll");
if(hinstDLL)
{
typedef DllClass*(*Factory)();
Factory fun1;
fun1 = (Factory)GetProcAddress(hinstDLL, "DllClass::getPCFilter");
The dll opens but the GetProcAddress is not finding the static factory method. dll 打开,但 GetProcAddress 未找到 static 工厂方法。 Am I not supposed to be able to do it this way?
我不应该这样做吗?
I've tried getting rid of the static method and instead, after the class declaration, doing the following:我尝试摆脱 static 方法,而是在 class 声明之后执行以下操作:
extern "C" DLLIMPORT void* getPCFilterInstance()
{
return (void*)new DllClass();
}
But then, when compiling the host source, the linker complains:但是,在编译主机源时,linker 抱怨:
In function `getPCFilterInstance'::
[Linker Error] undefined reference to `_imp___ZN8DllClassC1Ev'
This I can solve by linking to the.a lib.我可以通过链接到.a 库来解决这个问题。 But isn't the idea of the DLL to not need to link at compile time?
但是 DLL 的想法不是不需要在编译时链接吗?
You ignore the fact that the function name will be decorated ("name mangling") or not at all visible in the DLL interface (under the given name).您忽略了 function 名称将被修饰(“名称修改”)或在 DLL 界面(在给定名称下)中根本不可见的事实。 To my knowledge
GetProcAddress
doesn't do any name demangling, the linker however does (when statically importing a DLL with exported classes).据我所知,
GetProcAddress
不会进行任何名称修改,但是 linker 会进行(当静态导入带有导出类的 DLL 时)。
Best practice is to my knowledge to supply a factory function that has an undecorated name and a predefined calling convention much as COM prescribes it (see DllGetClassObject
).据我所知,最佳做法是提供一个工厂 function,它有一个未修饰的名称和一个预定义的调用约定,就像 COM 规定的那样(参见
DllGetClassObject
)。
Note: I should add that depending on the compiler/linker used, the decorated ("mangled") names will vary.注意:我应该补充一点,根据所使用的编译器/链接器,修饰的(“损坏的”)名称会有所不同。 Different compilers, different rules.
不同的编译器,不同的规则。 Therefore they may not even be compatible amongst each other without considerable tinkering.
因此,如果不进行大量修补,它们甚至可能彼此不兼容。
Edit: concerning the question:编辑:关于问题:
But isn't the idea of the DLL to not need to link at compile time?
但是 DLL 的想法不是不需要在编译时链接吗?
Well, yes and no.好吧,是的,不是。 On Windows the whole process is somewhat different from the process in unixoid systems.
在Windows上整个过程和unixoid系统中的过程有些不同。 The loader will take care of resolving dependencies and so on, but the point is that there are two ways of loading a DLL. One is by statically importing a DLL in which case the name resolution is done before your program gets to run (or fails before that) and the other is to load the DLL dynamically by means of
LoadLibrary
and friends and then resolve the function address with GetProcAddress
.加载程序将负责解决依赖关系等问题,但重点是有两种加载 DLL 的方法。一种是静态导入 DLL,在这种情况下,名称解析在程序运行(或失败)之前完成之前),另一种是通过
LoadLibrary
和朋友动态加载 DLL,然后使用GetProcAddress
解析 function 地址。 The latter has one variation (supported by the linker) called delay-loading.后者有一种变体(由链接器支持)称为延迟加载。 Ultimately it is still just the second method.
归根结底还是只是第二种方法。
It is possible that delay-loading offers exactly what you want, by having the linker care about the names to resolve and still being able to handle failure of loading the DLL or resolving a name at runtime.通过让 linker 关心要解析的名称并且仍然能够处理加载 DLL 或在运行时解析名称的失败,延迟加载可能会提供您想要的。
You can use extern "C"
statement to export your function with the same name as you've declared it in the code - otherwise it will get mangled by the c++ compiler您可以使用
extern "C"
语句导出 function 并使用与您在代码中声明的名称相同的名称 - 否则它将被 c++ 编译器破坏
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.