.NET 7 AOT 的使用以及 .NET 與 Go 互相調用

目錄

  • 背景
  • C# 部分
    • 環境要求
    • 創建一個控制臺項目
    • 體驗 AOT 編譯
    • C# 調用庫函數
    • 減少體積
    • C# 導出函數
    • C# 調用 C# 生成的 AOT
  • Golang 部分
    • 安裝 GCC
    • Golang 導出函數
  • .NET C# 和 Golang 互調
    • C# 調用 Golang
    • Golang 調用 C#
    • 其他
背景其實,規劃這篇文章有一段時間了,但是比較懶,所以一直拖著沒寫 。
最近時總更新太快了,太卷了,所以借著 .NET 7 正式版發布,熬夜寫完這篇文章,希望能夠追上時總的一點距離 。
本文主要介紹如何在 .NET 和 Go 語言中如何生成系統(Windows)動態鏈接庫,又如何從代碼中引用這些庫中的函數 。
在 .NET 部分,介紹如何使用AOT、減少二進制文件大小、使用最新的 [LibraryImport] 導入庫函數;
在 Go 語言部分,介紹如何使用 GCC 編譯 Go 代碼、如何通過 syscall 導入庫函數 。
在文章中會演示 .NET 和 Go 相互調用各自生成的動態鏈接庫,以及對比兩者之間的差異 。
本文文章內容以及源代碼,可以 https://github.com/whuanle/csharp_aot_golang 中找到,如果本文可以給你帶來幫助,可以到 Github 點個星星嘛 。
C# 部分環境要求SDK:.NET 7 SDK、Desktop development with C++ workload 。
IDE:Visual Studio 2022
Desktop development with C++ workload 是一個工具集,里面包含 C++ 開發工具,需要在 Visual Studio Installer 中安裝,如下圖紅框中所示 。
.NET 7 AOT 的使用以及 .NET 與 Go 互相調用

文章插圖
創建一個控制臺項目首先創建一個 .NET 7 控制臺項目,名稱為 CsharpAot 。
打開項目之后,基本代碼如圖所示:
.NET 7 AOT 的使用以及 .NET 與 Go 互相調用

文章插圖
我們使用下面的代碼做測試:
public class Program{static void Main(){Console.WriteLine("C# Aot!");Console.ReadKey();}}體驗 AOT 編譯這一步,可以參考官方網站的更多說明:
https://learn.microsoft.com/zh-cn/dotnet/core/deploying/native-aot/
為了能夠讓項目發布時使用 AOT 模式,需要在項目文件中加上 <PublishAot>true</PublishAot> 選項 。
.NET 7 AOT 的使用以及 .NET 與 Go 互相調用

文章插圖
然后使用 Visual Studio 發布項目 。
發布項目的配置文件設置,需要按照下圖進行配置 。
.NET 7 AOT 的使用以及 .NET 與 Go 互相調用

文章插圖
AOT 跟 生成單個文件 兩個選項不能同時使用 , 因為 AOT 本身就是單個文件 。
配置完成后,點擊 發布,然后打開 Release 目錄 , 會看到如圖所示的文件 。
.NET 7 AOT 的使用以及 .NET 與 Go 互相調用

文章插圖
.exe 是獨立的可執行文件,不需要再依賴 .NET Runtime 環境,這個程序可以放到其他沒有安裝 .NET 環境的機器中運行 。
然后刪除以下三個文件:
CsharpAot.expCsharpAot.libCsharpAot.pdb
光用 .exe 即可運行,其他是調試符號等文件,不是必需的 。
剩下 CsharpAot.exe 文件后,啟動這個程序:
.NET 7 AOT 的使用以及 .NET 與 Go 互相調用

文章插圖
C# 調用庫函數這一部分的代碼示例 , 是從筆者的一個開源項目中抽取出來的 , 這個項目封裝了一些獲取系統資源的接口,以及快速接入 Prometheus 監控 。
不過很久沒有更新了,最近沒啥動力更新 , 讀者可以點擊這里了解一下這個項目:
https://github.com/whuanle/CZGL.SystemInfo/tree/net6.0/src/CZGL.SystemInfo/Memory
因為后續代碼需要,所以現在請開啟 “允許不安全代碼” 。
本小節的示例是通過使用 kernel32.dll 去調用 Windows 的內核 API(Win32 API) , 調用 GlobalMemoryStatusEx 函數 檢索有關系統當前使用物理內存和虛擬內存的信息 。
使用到的 Win32 函數可參考:https://learn.microsoft.com/zh-cn/windows/win32/api/sysinfoapi/nf-sysinfoapi-globalmemorystatusex
關于 .NET 調用動態鏈接庫的方式,在 .NET 7 之前,通過這樣調用:
[DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)][return: MarshalAs(UnmanagedType.Bool)]internal static extern Boolean GlobalMemoryStatusEx(ref MemoryStatusExE lpBuffer);在 .NET 7 中 , 出現了新的操作方式

推薦閱讀