【问题标题】:LNK2019 when converting an app to use DLLs将应用程序转换为使用 DLL 时出现 LNK2019
【发布时间】:2010-12-06 17:12:52
【问题描述】:

(为了清楚起见重新编写)

我有一个多项目解决方案,我希望将其从使用 .lib 文件转换为 .DLL 文件。我创建了我的 __declspec 宏并将其应用于每个类,但项目中创建最终 .exe 的那些除外。然而,链接器几乎对所有东西都适用。我已设置为忽略有关导出模板对象的错误。

一个例子是这样的:

错误 LNK2019:未解决的外部 符号“__declspec(dllimport)公共: 无效 __thiscall Rail::SetNextRail(类 Rail *)" (__imp_?SetNextRail@Rail@@QAEXPAV1@@Z) 在函数“公共:静态”中引用 无效__cdecl MyUtilities::CreateBezierRails(int,class MyVector *,class std::vector > &)" (?CreateBezierRails@MyUtilities@@SAXHPAVMyVector@@AAV?$vector@PAVRail@@V?$allocator@PAVRail@@@std@@@std@@@Z) .obj

我的 __declspec(dllimport) 上的外部符号无法解析?这似乎不对。它被一个宏放置,例如:

#ifdef MYAI_EXPORT
#define DECLSPECAI __declspec(dllexport)
#else
#define DECLSPECAI __declspec(dllimport)
#endif

基本上,什么给了?为什么我会收到这些错误,我该如何解决?感谢到目前为止所有试图提供帮助的人,但我仍然坚持这一点。

【问题讨论】:

    标签: c++ dll visual-studio-2005 linker


    【解决方案1】:

    您是否链接到 MyRenderer.lib?

    【讨论】:

    • 是否存在项目依赖项(我正在使用 Visual Studio,抱歉)。是的
    • 所以.lib 文件列在项目属性> 配置属性> 链接器> 输入> 附加依赖项中?项目依赖是另一回事。
    • 感谢您的澄清。我添加了这个,现在得到“无法打开输入文件'MyRenderer.lib'。我去检查了,它在 MyRenderer 的输出/调试文件夹中,但不在 MyAI 的输出/调试文件夹中。
    • “附加库目录”的通用链接器选项中有一个设置,您可以将输出目录放入 MyRenderer。
    • 您可以通过为所有项目和配置定义中间目录$(SolutionDir)/obj/$(ProjectName) 和输出目录$(SolutionDir)/bin 来规避添加所有输出目录。
    【解决方案2】:

    您是否使用导出函数和类

    __declspec(dllexport)
    

    并使用

    导入它们
    __declspec(dllimport)
    

    ?如果没有,您将不得不这样做。在您的头文件中,在编译 DLL 期间,您将需要有 dllexport 子句,而在其他 DLL 或 EXE 中使用头文件时,您将必须使用 dllimport 子句。你可以通过定义一个宏来轻松做到这一点

    // set this in preprocessor options for the DLL
    #ifdef MYDLL
    # define MYDLL_IMPORTEXPORT __declspec(dllexport)
    #else
    # define MYDLL_IMPORTEXPORT __declspec(dllimport)
    #endif
    class MYDLL_IMPORTEXPORT MyClass {};
    

    【讨论】:

    • 是的!我有这个。虽然一些关于未解析外部符号的错误是“未解析的外部符号 __declspec(dllimport) public: void _thiscall Rail::SetNextRail”等
    【解决方案3】:

    它说它找到了一个声明但没有实现。您确定要编译包含函数实现的文件吗?您是否记得将 MyRenderer:: 放在 DrawVertices 调用之前?您确定将这两个库都链接到可执行文件中吗?

    编辑:当编译一个库时,库会留下一个存根,有效地说,当你可以将它链接到我时,我想要这个函数。

    当您运行链接器时,它会遍历所有库以查找这些存根并将它们“链接”到实际实现。您构建的每个 cpp 文件都会编译为一个目标文件,并且该目标文件的工作方式完全相同。如果它无法将存根链接到实际函数,那么您会收到一个链接器错误,例如您所看到的。因此,要么你的渲染器库没有链接到可执行文件,要么实现缺少一些重要的东西,比如 MyRenderer::。尽管如果是后者,我希望会出现其他问题,例如缺少 IDirect3DDevice,我认为它是该类的成员。因此,很可能,您无法将 .lib 链接到。

    【讨论】:

    • 我正在编译包含实现的文件,是的。在实现中,通过创建 MyRenderer 的实例然后使用 renderer->DrawVertices 来引用它。关于喜欢这两个库的可执行文件,我相信是这样,但我对此并不陌生。这编译并完美地作为 .lib 运行。
    • 听起来它必须是链接。我是 C++ 新手,所以很遗憾,我不知道该怎么做。
    【解决方案4】:

    DLL 有不同的配置。

    • 静态链接 DLL - 实现在 DLL 中,定义在 .lib 中。您静态链接到 .lib (有点像标题),并且 lib 告诉 c++ 如何调用该函数。这可能是你想要的。确保您的__declspecs 正确。
    • 动态链接 DLL - 一切都在 DLL 中,定义也在 DLL 中,您需要手动设置指向所有导出内容的函数指针,这些内容在运行时由字符串索引。

    Google 将提供帮助并制作此 CW,以便有人可以使此答案变得不那么糟糕。

    我还建议您让 DLL 在骨架应用程序中工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-22
      • 1970-01-01
      • 2015-09-03
      • 2011-09-20
      • 2023-04-07
      • 2014-09-10
      • 2011-05-23
      相关资源
      最近更新 更多