【问题标题】:DLL needs symbols (a class) from the app it will link toDLL 需要链接到的应用程序中的符号(类)
【发布时间】:2017-11-17 02:14:36
【问题描述】:

我无法获取要链接的 DLL,它需要从应用程序导出的类,该类将用于此 DLL。 Visual Studio 2008,Windows 7。

我有一个小的示例 DLL 编译(实际上是默认的 MSFT DLL 项目),应用程序可以正确使用 LoadLibrary()GetProcAddress()。我对 dllimport/dllexport 很有经验。使用 dumpbin /exports 对于发现与 GetProcAddress() 一起使用的错位名称至关重要(MSFT 的默认空 DLL 包括一个没有 extern "C" 的示例函数),但这是一个已解决的问题。

下一步是让应用导出一个 DLL 需要子类化的类。我执行 dllimport/dllexport #define 的操作与往常相反:编译应用程序时的特殊符号使用该标头使用 dllexport 和非应用程序代码(例如 DLL)标记类,没有特殊符号, 得到一个 dllimport 规范。 .exe 文件上的dumpbin /exports 准确地显示了正在导出的此类(损坏的)符号,没有其他符号,正如预期的那样。

下一步是让 DLL 包含标头并创建导出对象类型的对象(作为实际继承它的小步骤)。编译正常,但链接器显示错误:

DynTest.obj : error LNK2019: unresolved external symbol "public: __thiscall Test::Test(class Toast*,double)" (??0Test@@QAE@PAVToast@@N@Z) referenced in function "public: __thiscall CDynTest::CDynTest(void)" (??0CDynTest@@QAE@XZ)

好的,这并不让我感到惊讶,因为我知道在 WIN32 上我需要在链接时提供 DLL 来生成 DLL,这与我通常的 Unix 不同。由于 Windows 似乎对 DLL 和可执行文件的处理方式有点相似,因此我尝试在 Properties->Configuration Properties->Linker->Input->Additional Dependencies 中添加 .exe。这会得到一个错误,看起来像 LINK.EXE 没有自动检测到它被赋予了 .exe:

T:\mypath\MyBinary.exe : fatal error LNK1107: invalid or corrupt file: cannot read at 0x348

然后我尝试添加定义此类的目标文件...链接器似乎可以理解,并且可能成功满足了 DLL 的链接需求,但现在显示了该文件所依赖的无数其他符号.

所以我考虑重构应用程序,使其大部分位于 DLL 或 LIB 中,这样我就可以将其作为“附加依赖项”提供给我真正担心的 DLL。但这似乎是严厉的。这是我唯一的选择吗?

【问题讨论】:

  • 您是否希望能够更改 EXE 并使 DLL 使用新版本的超类?我不认为这是可能的。它似乎也不是超类的正确位置......应用程序使用 DLL,而不是相反。将超类放入 DLL 中。
  • 我希望重建应用程序并使用旧的 DLL,但不要更改 DLL 继承的类。 API 在这方面将保持稳定。符号不会改变(或重新排序,或在它们之前添加新符号,如果这些是 MSFT 无法处理的)。我同意这些要求可能看起来令人困惑,但这些是这个项目的要求。考虑允许用户自定义应用程序基类的 DLL。现在:我当然可以实现不同的技术实现逻辑模型。但模型并没有改变。

标签: c++ dll visual-studio-2008 windows-7 dllimport


【解决方案1】:

调用 dumpbin /exports 会为您提供 exe 导出的错位名称列表。您需要创建一个包含这些名称的模块定义文件 (.def):

EXPORTS
   @d3d_some_fancy_mangedled_method_1
   @d3d_some_fancy_mangedled_method_2
   ...

请注意,它基本上是删除了第一列的 dumpbin 输出。 然后使用lib 工具从模块定义文件生成导出库:

LIB /DEF:prog.def /NAME:prog.exe /MACHINE:x86

最后,您将生成的导出库prog.lib 链接到您的应用程序中。 /MACHINE 选项应该与您的可执行文件匹配。请注意,您不需要链接或无论如何使用程序可执行文件来链接它,只使用导出库。

【讨论】:

  • 感谢 VTT,正在尝试...它工作!但是 Q1:“删除了第一列”——dumpbin 输出的名称列的格式为“string = otherstring”。 LIB 似乎只对“otherstring”和“string = otherstring”感到满意。但是 DLL 构建的链接阶段仅适用于“string = otherstring”,所以我认为这是正确的——但你能确认一下吗? Q2:“将生成的导出库 prog.lib 链接到您的应用程序”是指 DLL,对吗?不是申请?
  • Q1:对我来说,dumpbin 输出包含 4 列:ordinalhintRVAname。只有name 是相关的。 Q2:没关系,可以链接到dll,也可以链接到exe。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-30
相关资源
最近更新 更多