【问题标题】:Making Visual C++ DLL from C++ class从 C++ 类制作 Visual C++ DLL
【发布时间】:2011-01-13 02:04:43
【问题描述】:

我有以下 C++ 代码来制作 dll (Visual Studio 2010)。

class Shape {
public:
  Shape() {
    nshapes++;
  }
  virtual ~Shape() {
    nshapes--;
  };
  double  x, y;   
  void    move(double dx, double dy);
  virtual double area(void) = 0;
  virtual double perimeter(void) = 0;
  static  int nshapes;
};

class __declspec(dllexport) Circle : public Shape {
private:
  double radius;
public:
  Circle(double r) : radius(r) { };
  virtual double area(void);
  virtual double perimeter(void);
};

class __declspec(dllexport) Square : public Shape {
private:
  double width;
public:
  Square(double w) : width(w) { };
  virtual double area(void);
  virtual double perimeter(void);
};

我有 __declspec,

class __declspec(dllexport) Circle

我可以使用以下命令构建一个 dll

CL.exe /c example.cxx
link.exe /OUT:"example.dll" /DLL example.obj 

当我尝试使用该库时,

Square* square; square->area()

我收到了错误消息。 有什么问题或遗漏?

example_unittest.obj:错误 LNK2001:未解析的外部符号“公共:虚拟双 __thiscall ... Square::area(void)" (?area@Square@@UAENXZ)

添加

根据wengseng的回答,我修改了头文件,对于DLL C++代码,我添加了

#define XYZLIBRARY_EXPORT

但是,我仍然遇到错误。

已解决

对于链接example.dll的主程序,我没有链接example.lib。

cl /MD /EHsc gtest_main.cc example_unittest.cc /I"./include" /link /libpath:"./lib" /libpath:"." gtest_md.lib example.lib /out:gtest_md_release.exe

添加后,一切正常。

【问题讨论】:

  • 我认为 DLL 必须使用 C 调用约定,这意味着没有 C++ 成员函数。不过,这只是我的想法。
  • 你是如何在 CL.exe 中导入类 Circle 的?
  • 您可以在 DLL 接口中导出 C++ 类。问题是 C++ 名称修改应用于导出的符号。由于没有名称修饰的标准,因此每个编译器都会以不同的方式进行操作。有时,同一编译器的不同版本会以不同的方式执行此操作。这通常是个坏主意。

标签: c++ windows visual-studio dynamic-linking


【解决方案1】:

在 DLL 中,我建议添加一个宏,并在预处理器中添加 XYZLIBRARY_EXPORT:

#if defined(XYZLIBRARY_EXPORT) // inside DLL
#   define XYZAPI   __declspec(dllexport)
#else // outside DLL
#   define XYZAPI   __declspec(dllimport)
#endif  // XYZLIBRARY_EXPORT

class XYZAPI Circle  

它将导出 Circle 类。

在EXE中,导入Circle类,不添加预处理器,默认会导入该类。

【讨论】:

  • 这似乎是编译器错误的最可能原因。编译器可能认为它应该导出 DLL 类而不是从 .lib 中导入它们
【解决方案2】:

您可以公开一个使用 C 调用约定的工厂函数并避免名称修改问题,而不是直接在 DLL 中导出 C++ 类。

class Shape {
  ...
};

class Circle : public Shape {
  ...
};

extern "C" Circle* newCircle();

extern "C" void deleteCircle(Circle* p);

然后,DLL 的用户可以调用 newCircle() 来创建一个 Circle 对象,对它做任何需要做的事情,然后调用 deleteCircle() 来摆脱它。您不能只对返回的指针调用 delete,因为 DLL 可能没有链接到与 DLL 的用户相同的 C++ 运行时库实例。

【讨论】:

    【解决方案3】:

    您必须导出 Shape 类来解决“static int Shape::nshapes”错误(可能还有其他错误)。

    不要忘记链接使用 DLL 生成的库(example.lib)

    【讨论】:

    • @prosseek:通过构建你的 dll 生成一个 lib 文件。此 lib 文件必须链接到您的测试程序中
    • 没错,这就是我添加的问题的解决方案。
    猜你喜欢
    • 1970-01-01
    • 2010-11-15
    • 1970-01-01
    • 1970-01-01
    • 2014-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多