C++ 中的 DLL 导出和继承

发布于 2024-11-19 08:23:19 字数 804 浏览 5 评论 0原文

我正在尝试从 DLL 中导出一个类及其基类,如下所示:

#ifdef MY_EXPORTS
    #define DECLSPEC_TEST __declspec(dllexport)
#else
    #define DECLSPEC_TEST __declspec(dllimport)
#endif


class DECLSPEC_TEST BaseClass
{
  // stuff.
};

class DECLSPEC_TEST DerivedClass : public BaseClass
{
  // This class only has a constructor which initializes the class differently.

};

但我尝试在另一个 DLL 中使用此类,我不断收到错误:

error LNK2019: unresolved external symbol 
"__declspec(dllimport) public: __thiscall DerivedClass::DerivedClass(void)"
 (__imp_??0DerivedClass@@QAE@XZ) referenced in function 
"public: __thiscall SomeOtherClass::SomeOtherClass(void)" (??0SomeOtherClass@@QAE@XZ)  

我还使用 PE Explorer 查看了我的导出 DLL,但无法查看导出列表中的派生类。

当我尝试在其他 DLL 中使用基类时,它工作正常。

我做错了什么?

I'm trying to export a class and its base class from a DLL like this:

#ifdef MY_EXPORTS
    #define DECLSPEC_TEST __declspec(dllexport)
#else
    #define DECLSPEC_TEST __declspec(dllimport)
#endif


class DECLSPEC_TEST BaseClass
{
  // stuff.
};

class DECLSPEC_TEST DerivedClass : public BaseClass
{
  // This class only has a constructor which initializes the class differently.

};

But I try to use this class in another DLL, I keep getting an error:

error LNK2019: unresolved external symbol 
"__declspec(dllimport) public: __thiscall DerivedClass::DerivedClass(void)"
 (__imp_??0DerivedClass@@QAE@XZ) referenced in function 
"public: __thiscall SomeOtherClass::SomeOtherClass(void)" (??0SomeOtherClass@@QAE@XZ)  

I also looked at my exporting DLL with PE Explorer and I can't see the derived class in the exports list.

When I try to use the base class in my other DLL it works fine.

What am I doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

信愁 2024-11-26 08:23:19

有两种方法加载DLL。第一种是引用 DLL 中的一个或多个符号(例如,您的类名),提供适当的导入 .LIB 并让链接器弄清楚一切。

第二种是通过LoadLibrary显式加载DLL。

这两种方法对于 C 级函数导出都适用。您可以让链接器处理它,也可以按照您的说明调用 GetProcAddress。

但当涉及到导出类时,通常只使用第一种方法,即隐式链接到DLL。

there are two ways to load the DLL. The first is to reference one or more symbols from the DLL (your classname, for example), supply an appropriate import .LIB and let the linker figure everything out.

The second is to explicitly load the DLL via LoadLibrary.

Either approach works fine for C-level function exports. You can either let the linker handle it or call GetProcAddress as you noted.

But when it comes to exported classes, typically only the first approach is used, i.e., implicitly link to the DLL.

独享拥抱 2024-11-26 08:23:19

好吧,我不知道如何解释这一点,但我将派生类构造函数的实现放在 CPP 文件中而不是在类定义中,错误就消失了...
谢谢大家:)

Ok, I don't know how to explain this but I put the implementation of the derived class' constructor in a CPP file instead of within the class definition and the error went away...
thanks everybody :)

多情癖 2024-11-26 08:23:19

链接器抱怨它找不到 DerivedClass 的构造函数。尝试显式声明它、定义它并从 DLL 中导出它:

DLL 的头文件:

class DECLSPEC_TEST BaseClass
{
};

class DECLSPEC_TEST DerivedClass : public BaseClass
{
public:
    DerivedClass();
};

DLL 的源 cpp 文件:

DECLSPEC_TEST DerivedClass::DerivedClass() { }

The linker is complaining that it can't find the constructor for DerivedClass. Try explicitly declaring it, defining it, and exporting it from your DLL:

Header file for DLL:

class DECLSPEC_TEST BaseClass
{
};

class DECLSPEC_TEST DerivedClass : public BaseClass
{
public:
    DerivedClass();
};

Source cpp file for DLL:

DECLSPEC_TEST DerivedClass::DerivedClass() { }
毁梦 2024-11-26 08:23:19

当您编译 DLL 时,您还会获得一个 .lib 文件。这是您的导入库。您将需要链接到它才能连接到此类链接时依赖项。

When you compiled your DLL, you also got a .lib file. This is your import library. You will need to link to it in order to connect to link-time dependencies like these.

久伴你 2024-11-26 08:23:19

需要检查的事项有:

  1. 确保链接到从 DLL 项目生成的确切 .LIB 文件。我们错误地构建了两个项目,但目标项目中的 LIB 文件已过时。
  2. 确保 DLL 项目中关联的 CPP 文件得到编译。不需要在所有方法上使用 __declspec 属性,因为您要导出整个类。
  3. 使用 Dependency Walker,确保 DLL 实际上导出了类及其所有方法。
  4. 确保两个项目中的 .LIB 文件之间不存在 64 位/32 位不匹配

Few things to check:

  1. Ensure you are linking with the EXACT .LIB file you are producing from DLL project. It happens, by mistake that we build both projects but LIB file in target project is obsolete.
  2. Ensure that associated CPP files, in DLL project, gets compiled.Using __declspec attribute on all methods is not required, since you are exporting entire class.
  3. Using Dependency Walker, ensure that DLL is actually having class and all its methods exported.
  4. Ensure that there is no 64-bit/32-bit mismatch among .LIB files in both projects
心意如水 2024-11-26 08:23:19

我在这里看到的唯一缺少的东西是类声明后面的分号 ; 。除此之外,导出应该可以正常工作。

还有一件事需要检查:您是否将派生类中的构造函数声明为 public

The only missing thing here that I see is a semicolon ; after the class declarations. Other than that, the export should work fine.

One more thing to check: Did you declare the constructor in the derived class to be public?

不知在何时 2024-11-26 08:23:19

据我了解,在您的 DerivedClass 中,您声明了一个非默认构造函数(即,与 DerivedClass::DerivedClass() 不同)。

在这种情况下,编译器不会为您生成默认构造函数,因此您必须定义一个默认构造函数,因为似乎由于某种原因您正在使用 DerivedClass 的默认构造函数(可能是在实现DerivedClass,不一定在使用 DLL 的代码中)。

没有必要在 DLL 接口中声明默认构造函数,但它应该存在。

如果您不愿意使用默认构造函数,可以使用以下技巧:

在 DerivedClass 定义的 private 部分中声明默认构造函数。

这样,任何使用它的尝试都会产生编译器错误(而不是链接器错误),以便您知道在哪里尝试使用默认构造函数并可以修复该问题。

As far as I understand, in your DerivedClass you have declared a non-default constructor (i.e., different from DerivedClass::DerivedClass()).

In such cases the compiler will not produce a default constructor for you, so you have to define one, since it seems that for some reason you are using the default constructor of your DerivedClass (possibly in the implementation of DerivedClass, not necessarily in the code that uses the DLL).

It is not necessary that the default constructor be declared in the DLL interface, but it should be there.

If you are not willing to have a default constructor, a trick is the following:

declare a default constructor in the private part of DerivedClass definition.

In this way, any attempt to use it will produce a compiler error (instead of a linker error), so that you know where you are trying to use the default constructor and can fix that.

清秋悲枫 2024-11-26 08:23:19

根据我的理解,我猜 SomeOtherClass 正在尝试调用 BaseClass() 的构造函数,而 BaseClass() 又调用 DerivedClass() 的构造函数,但由于 SomeOtherClass 没有 Derived 类的定义,所以它给出了错误,

可能的解决方案是将您的 SomeOtherClass 包含在该 DervideClass 中。

according to my understanding I guess SomeOtherClass is trying to call the constructor of your BaseClass(), which in turn is calling the constructor of your DerivedClass(), but since SomeOtherClass does not have the definition of Derived class, so it is giving an error,

Probable solution could be to include your SomeOtherClass in that DervideClass.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文