编译DLL中指定的接口

Compilation of interface specified in DLL

本文关键字:接口 DLL 编译      更新时间:2023-10-16

我在编译类时遇到链接问题,从另一个DLL的接口派生。这是代码。我有一个c++接口(抽象类),在DLL中这样指定:

// ============================ Source DLL
// header IFace.h"
#ifdef MY_EXPORTS
#define MY_API __declspec(dllexport)
#else
#define MY_API __declspec(dllimport)
#endif
class MY_API IFace
{
public:
    virtual ~IFace() {};
    virtual bool Foo() = 0;
};
// ============================ My DLL
// header
#ifdef MY_EXPORTS22
#define MY_API22 __declspec(dllexport)
#else
#define MY_API22 __declspec(dllimport)
#endif
#include "IFace.h"
class MY_API22 MyClass_Mock : public IFace
{
// IFace
public:
virtual ~MyClass_Mock() {};
virtual bool Foo() ;
};
// cpp file
bool MyClass_Mock::Foo()
{
    return true;
}

当我编译我的DLL时,它实现了接口IFace,我得到链接器错误:

  • 错误LNK2019:未解析的外部符号"__declspec(dllimport) "public: __cdecl IFace::IFace(void)"
  • 错误LNK2019: unresolved外部符号__declspec(dllimport) public: __cdeclIFace::IFace(类IFace const &)"
  • 错误LNK2019: unresolved__declspec(dllimport) public: class IFace &__cdeclIFace::operator=(class IFace const &)"
  • 错误LNK2001: unresolved__declspec(dllimport) public: class IFace &__cdeclIFace::operator=(class IFace const &)"

当我显式定义(或在c++ 11中删除)复制操作符和赋值操作符时,对于默认的ctor和dtor仍然有错误。

想链接到源DLL的.lib文件,因为我想在以后通过LoadLibrary动态加载它。我如何解决这个链接问题?

class MY_API IFace改为class IFace

如果指定MY_API源DLL将不导出IFace,因为它没有定义。另一方面,My DLL将尝试从源DLL导入IFace,但它将失败,因为没有导出IFace的定义。

如果你删除了MY_API,当我的DLL试图使用IFace时,声明它的头文件就足够了(即IFace.h)。

创建导出接口的dll是一个有问题的领域。

c++类没有标准的ABI,也不能保证类(代码兼容)与其他编译器的二进制兼容。

在Windows上有一种半形式的标准,其中类匹配COM对象,并且可以认为是兼容的。

内存管理

在Windows上malloc/freenew/delete是在运行时实现的。这可能是一个共享的运行时(例如msvcr120.dll),或编译成二进制文件(.dll,.exe)。如果在一个运行时(静态库)调用new,在另一个运行时调用delete,则会发生崩溃(免费调用不同的堆)。

为了避免这种情况,使用一个静态构造函数来构建你的类,并给出一个virtual删除函数,或者使用引用计数。

避免实现
virtual ~IFace() {};

上面的代码创建了头文件中定义的代码,该代码绑定到调用者中。如果此代码与实现不兼容,则可能调用错误的代码。为了确保只调用虚接口,您需要将接口类限制为可见函数,而不是实现。

class IFace {
  public:
    virtual Delete() = 0;
    virtual Method1() = 0;
...
};
IFace * MYAPI Constructor();实施

class MY_API IFace
{
  public:
    virtual bool Foo() = 0;
    virtual void Delete() = 0;
};

IFace * MY_API22 MyConstructor()

class MY_API22 MyClass_Mock : public IFace
{
// IFace
public:
  virtual void Deletor() { delete this };
  virtual bool Foo() ;
};
// cpp file
bool MyClass_Mock::Foo()
{
    return true;
}
IFace * MyConstructor()
{
     return new MyClass_Mock;
}