【问题标题】:Unresolved Symbol Errors for C++/CLI dll in C++ ProjectC++ 项目中 C++/CLI dll 的未解决符号错误
【发布时间】:2018-11-25 14:54:51
【问题描述】:

我正在尝试一个非常简单的 C++/CLI 包装器实现,以允许旧版 C++ 代码引用 .Net 代码,如 described here。我只是试图将我的基本 C++/CLI 非托管(本机)对象链接起来,甚至不包含任何托管/IL/.Net 代码。

我的问题是,按照这个基本设置和我在下面描述的内容,我是否对这些错误感到非常困惑?是否有一些我遗漏的注意事项?也许答案是这应该有效,所以不清楚哪里出了问题。那还是有帮助的。类似的工作示例会很棒。

未解决的符号错误

错误 LNK2019 未解析的外部符号“__declspec(dllimport) 公共:__thiscall Wrapper::Test::Test(void)" (__imp_??0Test@Wrapper@@QAE@XZ) 在函数_main NativeApp中引用

错误 LNK2019 未解析的外部符号“__declspec(dllimport) 公共:__thiscall Wrapper::Test::~Test(void)" (__imp_??1Test@Wrapper@@QAE@XZ) 在函数_main NativeApp中引用

我已经查看了有关 SO 的相关问题,但没有任何运气。我的 dll 标头包含在客户端 C++ 项目中,我的项目对 C++/CLI 包装器 dll 的引用,以及用于导入/导出的定义语句。我非常简单的代码如下所示。我没有使用任何 MFC。 我正在使用 VS2017DumpBin.exe /exports 显示的导出符号似乎与链接器错误所说的缺失相匹配。

      1    0 000010D0 ??0Test@Wrapper@@QAE@XZ = ??0Test@Wrapper@@QAE@XZ (public: __thiscall Wrapper::Test::Test(void))
      2    1 000010E0 ??1Test@Wrapper@@QAE@XZ = ??1Test@Wrapper@@QAE@XZ (public: __thiscall Wrapper::Test::~Test(void))
      3    2 000010C0 ??4Test@Wrapper@@QAEAAV01@ABV01@@Z = ??4Test@Wrapper@@QAEAAV01@ABV01@@Z (public: class Wrapper::Test & __thiscall Wrapper::Test::operator=(class Wrapper::Test const &))

这是基本代码...

NativeApp.exe(项目)


NativeApp.cpp(文件)

#include "stdafx.h"
#include <iostream>
#include "Wrapper.h" //From additional includes directory

int main()
{
    std::cout << "Program Started" << std::endl;
    Wrapper::Test shell = Wrapper::Test::Test(); //Use dll
    std::cin.get();
    return 0;
}

对 Wrapper 的引用


Wrapper.dll(项目)


Wrapper.cpp(文件)

#include "Wrapper.h"

#pragma unmanaged
namespace Wrapper {
    Test::Test() {
    }
    Test::~Test() {
    }
}

Wrapper.h(文件)

#pragma once

#ifdef WRAPPER_EXPORTS  
#define WRAPPER_API __declspec(dllexport)   
#else  
#define WRAPPER_API __declspec(dllimport)   
#endif  

#pragma unmanaged
namespace Wrapper {
    class WRAPPER_API Test {
    public:
        Test();
        ~Test();
    };
}

【问题讨论】:

  • 为什么投反对票?说真的,知道为什么会有所帮助吗?我看到很多关于 SO 的相关问题,因此该主题有先例,但这个问题在细节上是独一无二的。
  • 虽然基本思想(使用 C++/CLI 作为 .NET 和 C++ 代码之间的层)非常可靠,但基本上您方法的所有细节都是错误的。 __declspec(dllexport) 不被 C++/CLI 使用,也不会生成 C# 所需的 .NET 元数据。 #pragma unmanaged 导致只能由其他 C++ 代码访问的内容( 可能从 C# 中看到其他 C++ 代码)。要制作 C# 可用的对象,您需要在 C++/CLI 端使用 public ref class
  • 反之亦然。 #pragma unmanaged 代码不能使用 .NET 的东西,它只能调用其他 C++ 代码(那个 C++ 代码可以使用 #pragma managed 和 .NET)。对于您所描述的(在用 C++ 编写的主应用程序中包装对 C# 的调用),没有理由使用 DLL。只需将 C++ 和 C++/CLI 文件一起链接到 EXE 中。
  • 如果您删除 __declspec 内容,并将项目引用更改为 "link library dependencies",您的原生 C++ 对象共享应该开始工作。
  • dumpbin 输出显示了一个名为 NativeShell 的类的构造函数和析构函数。无法猜测在代码 sn-p 中它是如何变成“测试”的。

标签: c++ dll c++-cli


【解决方案1】:

我的印象是项目引用在幕后处理了任何其他依赖项设置。显然,事实并非如此。需要将 .lib 文件添加为附加依赖项as is described here。但是,作为described by this Microsoft document,当我使用非/clr dll 时,一切都没有额外的依赖项,所以我不确定为什么我的CLR 引用只需要额外的依赖项。显然,我需要进一步了解这一点。

无论如何,下面列出了我的 C++ 客户端项目要求。我错过了第二个要求。另外,here is an example project 帮助我诊断了问题。

1.) 添加项目参考

2.) 将 .lib 文件添加为“附加依赖项”。

[可选] 使用Additional Library Directories

3.) #include.h 文件在适当的代码中

[可选]使用额外的包含目录

编辑:为什么需要额外的依赖,以及替代选项

如上所述,我一直在纠结为什么 /clr dll 需要 .lib 附加依赖项,而非非 clr dll 则不需要。答案是因为 /clr 项目默认配置为忽略导入库。因此,当项目被另一个 C++ 项目引用时,项目引用会忽略导入库。在 /clr dll 项目中将此设置(链接器 > 常规 > 忽略导入库)更改为“否”可以解决问题,因此不需要额外的依赖项,并且项目引用的工作方式与非 clr C++ dll 相同。

【讨论】:

  • CLR 引用使用 .NET 元数据,正如我们之前所讨论的,它不包括本机导出。很高兴你让它工作了,但要注意在导出类时,编译器版本、运行时库版本和编译设置必须匹配。没有什么是解耦的。
猜你喜欢
  • 2012-03-20
  • 1970-01-01
  • 1970-01-01
  • 2021-10-30
  • 1970-01-01
  • 2014-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多