CLI項目遷移至.NET Core平臺

蠍子

在Visual Studio 2019(自v16.4開始)和.NET Core 3.1中,一項引人關注的新特性是可以面向.NET Core來構建C++/CLI項目。具體怎麼做呢?

有兩種方法:一種是直接通過cl.exe和link.exe(使用/clr:netcore編譯開關),二是使用MSBuild(通過<clrsupport>NetCore/<clrsupport>。

在今天這篇文章中,我將會向大家演示如何將一個簡單的C++/CLI項目遷移至.NET Core的整個過程,如果大家有什麼疑問,可以查閱.NET Core附帶的幫助文檔。

一個簡單的項目

首先,我需要準備一個簡單的示例項目來開始這次實驗。我將使用一個帶有原生入口點(native entry point)的應用程序,這個應用程序將會通過C++/CLI來顯示一個Windows窗口。另外,也可以使用C++/CLI,通過將託管入口點(managed entry point)與本機依賴項進行互操作的方式來對項目進行遷移,也同樣容易。下面,我將創建了一個示例解決方案,這個解決方案中包含三個簡單項目。

1. NativeApp

這個項目使用了Visual Studio的Windows桌面應用程序模板進行創建。

1.1. 它將會成為應用程序的入口點。

1.2. 我對這個項目進行了一些修改,使它可以顯示CppCliInterop項目中的一個託管窗口,並在IDM_ABOUT命令被觸發時調用一個方法。


2. ManagedLibrary

這個項目是一個C#版本的Windows窗口庫,面向.NET Core。

2.1 這個項目將會為NativeApp提供一個窗口來顯示。

2.2 我在這個窗口上添加了一個文本框和一個用來設置文本框內容的方法。另外,我還將這個項目配置為同時面向.NET Core和.NET Framework,因此這兩類平臺都可以使用它。通過這種方式,我們可以專注於C++/CLI項目的遷移。


3. CppCliInterop

這是一個.NET Framework C++/CLI 庫項目。

3.1 這個項目將會作為一個互操作層,用來連接NativeApp項目和ManagedLibrary項目。

3.2 它將會引用到ManagedLibrary項目,並允許NativeApp項目來使用它。

3.3 這個項目將會需要被遷移到.NET Core。

上面的例子可以在GitHub上找到。當你啟用NativeApp程序時,如果你點擊[Help->About]菜單,一個Windows窗口將會被顯示出來,同時這個窗口上的文本框的內容將會使用NativeApp傳入的內容。

將一個vcxproj項目遷移到.NET Core

現在開始,我們將進入有趣的部分:通過更新我們的示例App來使它可以運行在.NET Core上。實際上,為了達到這個目標,我們只需要修改很小的一部分代碼。如果你之前有嘗試過將C#遷移到.NET Core的話,那麼遷移C++/CLI項目將會十分簡單,因為項目文件格式都不需要改變。

對於託管項目來說,.NET Core和.NET Standard項目使用新的SDK樣式的項目文件格式。但是,對於C++/CLI項目,使用相同的vcxproj文件格式將同時面向.NET Core和.NET Framework這兩個目標平臺。

具體來說,我們所需要修改的地方就是項目文件。我們可以通過Visual Studio來方便的完成部分的修改,但還有一部分(例如添加WinForms引用)還是需要手動進行。因此,當前修改項目文件的最簡單方法是先在VS中卸載項目,然後在VS Code或者記事本等文本編輯器中直接修改vcxproj文件。步驟如下:

1. 將<clrsupport>true/<clrsupport>修改為<clrsupport>NetCore/<clrsupport>。這將指示編譯器在編譯的時候使用/clr:netcore,而不是/clr。

1.1 如果你喜歡的話,這項修改可以直接在Visual Studio的項目屬性裡直接修改。

1.2 請注意,屬性<clrsupport>在項目的各個配置/平臺相關的屬性裡都有指定,所以我們將會在4個不同的地方進行這樣的修改。/<clrsupport>

2. 將<targetframeworkversion>4.7/<targetframeworkversion>修改為<targetframework>netcoreapp3.1/<targetframework>。

2.1 這項修改可以在Visual Studio裡的[高級]配置頁面進行修改。但是,需要注意了,修改一個項目的CLR支持設置不會自動的修改<targetframeworkversion>,所以需要在選擇.NET Core Runtime支持之前,記得先清除掉[.NET Target Framework Version]這個設置值。/<targetframeworkversion>

3. 修改.NET Framework的引用(到System, System.Data, System.Windows.Forms, and System.Xml),使之可以引用到Windows Desktop .NET Core SDK裡的WinForm組件。這項修改目前還不能直接在Visual Studio中進行,所以它必須手動進行修改。請注意,只需要添加Windows Destop SDK的引用,因為.NET Core SDK(包含了諸如System, System.Xml等系統庫)已經自動被引用了。對於WinForms,WPF或者兩者都會使用到不同的框架引用。如下圖所示:

試試看:將你的C++/CLI項目遷移至.NET Core平臺

通過以上這些修改,我們的C++/CLI項目終於可以面向.NET Core平臺進行成功的編譯了。如果你使用的是最新版本的Visual Studio(v16.5或者v16.6 Preview 1)的話,項目還可以成功的跑起來。至此,遷移過程完成。

在Visual Studio 2019 v16.5 Preview 2之前,C++/CLI庫還不會生成.runtimeconfig.json這個文件。這個文件對於指示項目使用到的.NET Core版本十分有用,所以需要手動添加這個文件。所以,如果你使用的是一個比較舊的Visual Studio版本,那麼你需要手動創建CppCliInterop.runtimeconfig.json文件並將它拷貝到輸出文件夾,如下圖所示:

試試看:將你的C++/CLI項目遷移至.NET Core平臺

經過修改之後的應用程序可以運行在.NET Core上了。我們也將修改之後的版本放到了相同的GitHub頁面供大家參考。在下圖中,顯示了兩個Windows窗口,一個是我們的NativeApp窗口,一個是ManagedLibrary窗口,另外還顯示了目前已加載模塊列表,其中,我們可以看到coreclr.dll已經成功加載到應用程序進程空間了。

試試看:將你的C++/CLI項目遷移至.NET Core平臺

不使用MSBuild來進行編譯

在上面的遷移例子中,我們只需要將項目文件更新的目標平臺修改為.NET Core即可。如果你是直接使用cl.exe和link.exe來構建你的C++/CLI程序集,別擔心,也是可以支持的。

具體步驟如下:

1. 當調用cl.exe時,使用/clr:netcore,替換掉/clr。

2. 使用/FU來引用必要的.NET Core程序集(.NET Core程序集一般安裝在這個文件夾下[%ProgramFiles%\\dotnet\\packs\\\\\\ref])。

3. 當執行鏈接的時候,將.NET Core app host目錄當做一個LibPath。.NET Core app host文件一般安裝在這個文件夾[%ProgramFiles%\\dotnet\\packs\\Microsoft.NETCore.App.Host.win-x64\\\\runtime\\win-x64\\native]。

4. 確保ijwhost.dll(這個文件用來啟動.NET Core運行時)文件從.NET Core app host位置被拷貝出來。當編譯一個vcxproj項目時,MSBuild會自動完成這個拷貝工作。

5. 創建一個.runtimeconfig.json文件,原因在上面已經說過了。

一些說明

你可以看到,藉助Visual Studio 2019和.NET Core 3.1,將我們的C++/CLI項目遷移到.NET Core平臺是非常容易的,但是還需要注意的是,還有一些C++/CLI方面的限制。

具體如下:

1. C++/CLI支持只在Windows平臺可用,即使它運行在.NET Core平臺。如果你需要進行一些跨平臺的互操作,則可以參考[platform invokes]方面的內容。

2. C++/CLI項目不能面向.NET Standard,它只能面向.NET Core或者.NET Framework,且不能將它們同時作為目標平臺,因此,如果你希望構建一個同時使用.NET Framework和.NET Core的項目,你將需要使用兩套不同的項目文件。

3. 如果一個項目使用到了.NET Core平臺上不支持的API,這個API調用將會被轉換為.NET Core上的替代API。我們可以藉助[.NET Portability Analyzer]這個工具來幫助我們找到那些不能在.NET Core上正常工作的框架依賴項。

總結

感謝大家花功夫閱讀這篇”大傢伙”,通過本文,我們可以基本瞭解C++/CLI項目遷移到.NET Core平臺的大致過程。

但是對於我個人來說,還是老老實實地用我所熟悉的那套C++吧。


試試看:將你的C++/CLI項目遷移至.NET Core平臺


分享到:


相關文章: