閱讀英文

共用方式為


教學課程:在 CLR 應用程式中安裝原生相依性

C++/CLI 是一項技術,可讓您將 .NET 類別與原生C++類型結合,以建立採用C++程序代碼並讓 .NET 程式存取的連結庫和應用程式。

您可以搭配 C++/CLI 使用 vcpkg,在以 Common Language Runtime (CLR) 為目標的專案中安裝及取用C++相依性。

在本教學課程中,您將了解如何:

必要條件

建置範例 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 將訊息列印至主控台。 連結 fmt 庫會透過 vcpkg 安裝,並在取用項目中連結。

若要編輯原始程序檔,請在 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 指令清單 設定為 [是]
  • Instal Vcpkg 相依性 設定為 [是]
  • 使用 AutoLink 設定為 [是]
  • 應用程式本機部署 DLL 設定為 [是]

MixedLibrary 項目屬性

啟用 vcpkg 的必要專案

有了這些變更,Visual Studio 現在會先讀取 vcpkg.json 檔案,並自動安裝指令清單中包含的相依性,再建置專案。

在 [屬性] 頁面中,我們也想要讓 /utf-8 旗標正確建 fmt 置。

在 C/C++ 設定的 [命令行] 子區段編輯要包含在 /utf-8 中的 [其他選項]

最後,按兩下 [確定] 關閉 [屬性] 頁面。

4 - 確認 vcpkg 是否正常運作

如果一切都已正確設定,Visual Studio 會叫用 vcpkg 來安裝相依性,再建置MixedLibrary專案。

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 無法建置,請確定您已正確遵循上述步驟,包括新增 /utf-8 C/C++ > 命令行中的其他選項。

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++程式代碼將訊息列印至主控台。 上述變更會讓 fmt 連結庫在 CLR 應用程式中取用。

不需要應用程式的專案,只要建置並執行 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

下一步

另請瞭解其他有用的功能: