从同一个DLL导出带有impl的DLL API和工厂

Exporting DLL API and Factory with impls from same DLL

本文关键字:DLL API impl 工厂 同一个      更新时间:2023-10-16

好吧,我开始明白为什么它被称为Dll地狱了
这是我得到的代码

// 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中的原始问题。除非我也为它们创建创建函数,但对于简单的数据结构来说,这似乎有点太大的开销。

因此,基本上的问题是,如何在不将IData导出到DLL中的情况下向客户端公开CCD_5?

如果你正在开发COM这样的东西:没有必要通过导出接口

__declspec(dllexport|import).

调用约定是一个相当古老的概念,在x64上具有任何相关性(Windows和UNIX都只有一个64位调用约定!)您可以在32位上选择__cdecl__stdcall。第一条规则应该是:保持一致!这两种约定本身都很好

COM和WinAPI使用__stdcall,而标准库大多使用__cdecl。就性能而言,这是完全无关的(stackoverflow上有一篇关于调用约定的速度差异的帖子)。

警告可能是由于您正在导出类而不是构造函数,因此我建议不要导出类。。。