好的,我开始理解为什么它叫做Dll Hell 这是我得到的代码
// API.h file
#ifdef EXPORTS
#define API __declspec(dllexport)
#else
#define API __declspec(dllimport)
#endif
struct API IClass {
virtual void foo() = 0;
}
extern "C" API IClass* CreateClass(const char* type);
// Impl1.h
class Impl1: public IClass
{
//...
}
// API.cpp file
#include "Impl1.h"
#include "Impl2.h"
#include "ImplX.h"
extern "C" API IClass* CreateClass(const char* type)
{
if (type == "type1")
return new Impl1();
// ...
return 0;
}
我收到链接器警告
warning LNK4217: locally defined symbol ??0IClass@DG@@QAE@XZ (public: __thiscall IClass::IClass(void)) imported in function...
我理解这种情况正在发生,因为我已经在我的所有Impl中导入了这些符号,但另一方面,它们现在是本地的,因为我在工厂中编译它们是API的一部分。
1)我应该忽略这个警告还是有不同的方法来解决这个问题? 2)我应该保留默认的__thiscall还是更改为__stdcall?
修改
不导出IClass
帮我删除了警告
另一个问题是,我不确定相同的方法可以解决这个问题
我们假设IClass
也有方法virtual bar(IData* data) = 0
如果我希望客户能够创建IData
的实例,我需要将其导出到dll中,返回到impl中的原始问题。除非我也为它们创建了创建函数,但对于简单的数据结构来说这似乎有点开销。
基本上问题是,如何在不将它们导出到DLL的情况下向客户端公开IData
?
答案 0 :(得分:2)
如果您正在使用类似COM的东西:无需通过
导出界面__declspec(dllexport|import).
调用约定是一个相当古老的概念,与x64有任何关联(Windows和UNIX只有一个64位调用约定!)您在32位上的选择将在__cdecl
或__stdcall
之间。数字1规则应该是:保持一致!这两个惯例本身都很好。 (除非你打算使用va_args
(你不应该使用它,因为它们是纯粹的邪恶)......)
__stdcall
,而标准库主要使用__cdecl
。在性能方面,它完全无关紧要(在这里有关于调用约定的速度差异的stackoverflow上的帖子)。
警告可能是因为您导出的是类而不是构造函数,因此我建议不要导出类...