使用来自同一DLL的impls导出DLL API和Factory

时间:2012-07-25 10:54:28

标签: c++ dll dllimport dllexport

好的,我开始理解为什么它叫做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

1 个答案:

答案 0 :(得分:2)

如果您正在使用类似COM的东西:无需通过

导出界面
__declspec(dllexport|import).

调用约定是一个相当古老的概念,与x64有任何关联(Windows和UNIX只有一个64位调用约定!)您在32位上的选择将在__cdecl__stdcall之间。数字1规则应该是:保持一致!这两个惯例本身都很好。 (除非你打算使用va_args(你不应该使用它,因为它们是纯粹的邪恶)......)

COM和WinAPI使用

__stdcall,而标准库主要使用__cdecl。在性能方面,它完全无关紧要(在这里有关于调用约定的速度差异的stackoverflow上的帖子)。

警告可能是因为您导出的是类而不是构造函数,因此我建议不要导出类...