【发布时间】: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。 我正在使用 VS2017。 DumpBin.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 中它是如何变成“测试”的。