0

我有两个模块,每个模块都有自己的类和自己的对象。每个模块都被编译成一个 DLL。我想进行“跨 DLL”方法调用,具有指向另一个类的对象的指针,但链接器不允许这样做(MSVC++ 2008)。

进一步来说:

  • 有calledModule.cpp,有calledClass,以及这个类的对象(calledObject);类有calledMethod,我想调用它;模块被编译为 DLL 并成为(惊喜!)称为 Lib.dll。
  • 有callingModule.cpp,有callingClass;除其他外,该类具有属性,它是指向被调用对象的指针;模块被编译为DLL调用Lib.dll;calledObject 上的指针在构造函数中设置。

我能够编译整个代码。当链接器启动时,麻烦就来了。我得到以下信息:moduleCalling.obj:错误 LNK2001:未解析的外部符号“public:void __thiscall classCalled::methodCalled ...”

我不使用任何 declspec 的东西,所以什么都不会从 calledLib.dll 中导出。

我正在调用的方法(methodCalled)存在于实现中,它的原型在标头中正确声明。classCalled 是一个“基本”类,不是从任何东西继承的。此外,当我将 methodCalled 声明为虚拟...

我很难理解,为什么我不能以“正常”的方式从另一个 DLL 调用对象的方法?为什么将其声明为“虚拟”会有所帮助?有谁知道?我有一些猜测,但专家的回答将有助于理解这些东西。

PS:我使用的是 MSVC++ 2008。

谢谢!

更新:添加代码片段,它反映了代码的外观。

// part of calledLib.dll
// moduleCalled.h

class classCalled {
  public:
    int methodCalled() { return 1 };
};

// ---------------------------------------------------------------
// part of callingLib.dll
// moduleCalling.h

#include "moduleCalled.h"

class classCalling {
  public:
    classCalled* ref;
    void justSomeMethod();
};

// ---------------------
// moduleCalling.cpp

#include "moduleCalling.h"

void classCalling::justSomeMethod() {
  ref = new classCalled();
  int a = ref->methodCalled(); // <--- this is not allowed by linker,
                               // unless methodCalled is made virtual.
}
4

1 回答 1

1

链接器链接来自不同模块的代码片段。如果您有从一个模块到另一个模块的调用,链接器必须知道您正在调用的函数是在哪个其他模块中实现的,并用真实地址替换调用。这是一个非常粗略的画面,但足以了解发生了什么。

在您的情况下,链接器必须知道您的函数位于 calledLib.dll 中。因此,您必须链接到引用称为 Lib.dll 的内容。这个东西叫做导入库。它的名字应该叫做Lib.lib。为了生成它,您应该编写一个 .def 文件,但是对于类方法来说很难,因为链接器使用的类方法名称看起来与它们在 C++ 代码中的样子非常不同。或者您可以使用 declspecs。它将生成正确的 calledLib.lib,您必须将其与您的 callingLib.dll 链接。

于 2013-01-31T15:38:54.463 回答