C++/CLI 是一种技术,可用于将 .NET 类与本机 C++ 类型相结合,以创建采用 C++ 代码并使其可供 .NET 程序访问的库和应用程序。
可以将 vcpkg 与 C++/CLI 结合使用,在面向公共语言运行时 (CLR) 的项目中安装和使用 C++ 依赖项。
在本教程中,您将学习如何执行以下操作:
先决条件
- vcpkg
- Git
- Visual Studio 的开发人员 Powershell
- 含以下组件的 Visual Studio:
生成示例 C++/CLI
在本教程中,我们将从现有的 C++/CLI 应用程序开始,并添加随 vcpkg 一起安装的 C++ 依赖项。 本教程中的命令假定正在适用于 Visual Studio 的 开发人员 PowerShell 中运行它们。
1 - 克隆示例存储库
第一步是在 .NET 示例存储库中获取 C++/CLI 示例应用程序的副本。 C++/CLI 示例应用程序位于 core/interop/cpp-cli
文件夹中。
git clone https://github.com/dotnet/samples
2 - 导航到示例应用程序文件夹
cd samples/core/interpo/cpp-cli
2 - 检查项目是否正确生成并运行
示例存储库包含一个包含四个项目的解决方案:
- ManagedLibrary:适用于 .NET 的 C# 库
- MixedLibrary:将 ManagedLibrary 中的本机 C++ 代码和 .NET 代码混合的库
- NativeApp:使用 MixedLibrary 中的 .NET 代码的 C++ 应用程序
- ManagedApp:使用 MixedLibrary 中的 C++ 代码的 C# 应用程序
运行以下命令以生成解决方案的项目:
msbuild CPP-CLI.sln -restore
如果生成失败,请确保已安装先决条件部分中列出的 Visual Studio 所需组件,并且满足示例应用程序的 .NET 5.0 SDK 或更高版本和 Visual Studio 2019 16.8 或更高版本的最低要求。
生成后,可以运行 ManagedApp.exe
./bin/Debug/x64/ManagedApp.exe
该程序生成以下输出:
=== Managed class ===
Hello from ManagedClass in MixedLibrary
Hello from NativeClass in MixedLibrary
-- message: from managed app!
=== P/Invoke ===
Hello from NativeEntryPoint_CallNative in MixedLibrary
Hello from NativeClass in MixedLibrary
-- message: from managed app!
3 - 在 Visual Studio 中打开项目
在后续步骤中,我们将修改库以使用 fmt
将消息打印到控制台。 将通过 vcpkg 安装 fmt
库,并在使用项目中链接该库。
若要编辑源文件,请在 Visual Studio 中打开 CPP-CLI.sln 解决方案:
start CPP-CLI.sln
在 Visual Studio 中打开解决方案后,可能会收到将项目重定向到最新版本的提示。 可以单击“确定”来将 Windows SDK 版本和平台工具集升级到最新版本。
项目的目标 Windows SDK 版本和平台工具集版本到最新版本。
添加 C++ 本机依赖项
接下来,我们将对 MixedLibrary 项目进行以下更改。
- 添加 vcpkg 清单以获取
fmt
。 - 在项目中启用 vcpkg。
- 将
NativeClass::Hello
修改为使用fmt
打印消息。
1 - 创建 vcpkg 清单
右键单击 NativeLibrary 项目,然后单击上下文菜单中的“添加 > 新项”。
命名新项 vcpkg.json
,这是 vcpkg 清单文件,并确保该文件是在项目文件夹的根目录中创建的。
2 - 将 fmt
添加为依赖项
打开 vcpkg.json
文件并编辑其内容以匹配以下内容:
{
"dependencies": [ "fmt" ]
}
如果 vcpkg 清单文件位于正确的位置并且尝试生成项目,则会收到以下警告:
The vcpkg manifest was disabled, but we found a manifest file in samples\core\interop\cpp-cli\MixedLibrary\. You may want to enable vcpkg manifests in your properties page or pass /p:VcpkgEnableManifest=true to the msbuild invocation.
3 - 在 MixedLibrary 的属性中启用 vcpkg
右键单击项目并单击“属性”选项,打开 MixedLibrary 的“属性”页面。
更改 vcpkg 部分中的以下属性:
- “使用 Vcpkg”设置为“是”
- “使用 Vcpkg 清单”设置为“是”
- “安装 Vcpkg 依赖项”设置为“是”
- “使用自动链接”设置为“是”
- “应用本地部署 DLL”设置为“是”
启用 vcpkg 所需
进行这些更改后,Visual Studio 现在将读取 vcpkg.json
文件,并在生成项目之前自动安装清单中包含的依赖项。
在“属性”页面中,我们还希望启用 /utf-8
标志,以便正确创建 fmt
生成。
在 C/C++ 设置的“命令行”子部分中,编辑其他选项以将 /utf-8
包含在以下项中:
最后,单击“确定”关闭“属性”页面。
4 - 验证 vcpkg 是否正常工作
如果正确配置了所有内容,Visual Studio 将在生成 MixedLibrary 项目之前,调用 vcpkg 来安装依赖项。
1>Installing vcpkg dependencies to C:\path\to\samples\core\interop\cpp-cli\MixedLibrary\vcpkg_installed\x64-windows\
1>"C:\path\to\vcpkg\vcpkg.exe" install --x-wait-for-lock --triplet "x64-windows" --vcpkg-root "C:\path\to\vcpkg\" "--x-manifest-root=C:\path\to\samples\core\interop\cpp-cli\MixedLibrary\" "--x-install-root=C:\path\to\samples\core\interop\cpp-cli\MixedLibrary\vcpkg_installed\x64-windows\"
如果未看到 vcpkg 输出,或者 fmt
无法生成,请确保正确执行上述步骤,包括在 C/C++ > 命令行中的“其他选项”中添加 /utf-8
。
4 - 修改项目的源代码
最后,我们希望将 MixedLibrary.cpp
文件修改为使用 fmt
将消息打印到控制台。 对源代码进行以下更改:
1 - 包括 fmt/printf.h
标头(第 5 行)。
#include <iostream>
#include <vcclr.h>
#include <fmt/printf.h>
2 - 将 NativeClass::Hello
函数修改为使用 fmt::println
(第 44 行)。
void MixedLibrary::NativeClass::Hello(const wchar_t *msg)
{
auto ws = std::wstring(msg);
auto str = std::string(ws.length(), 0);
std::transform(ws.begin(), ws.end(), std::back_inserter(str), [](wchar_t c) { return static_cast<char>(c); });
fmt::println("Hello from NativeClass in MixedLibrary");
fmt::println("-- message: {}", str);
fmt::println("-- printed using FMT version {}", FMT_VERSION);
}
构建应用程序
NativeClass::Hello
函数在 ManagedApp 项目中用于使用 C++ 代码将消息打印到控制台。 上述更改使得可在 CLR 应用程序中使用 fmt
库。
不需要更改应用程序的项目,只需生成并运行 ManagedApp 项目。
程序输出应如下内容:
=== Managed class ===
Hello from ManagedClass in MixedLibrary
Hello from NativeClass in MixedLibrary
-- message: from managed app!
-- printed using FMT version 110002
=== P/Invoke ===
Hello from NativeEntryPoint_CallNative in MixedLibrary
Hello from NativeClass in MixedLibrary
-- message: from managed app!
-- printed using FMT version 110002
后续步骤
另请了解其他有用的功能: