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


CsharpExport.dll 復制到 CsharpAot 項目中 , 并配置 始終復制 。

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

文章插圖
CsharpAotNative 中加上:
[LibraryImport("CsharpExport.dll", SetLastError = true)][return: MarshalAs(UnmanagedType.I4)]internal static partial Int32 Add(Int32 a, Int32 b);
.NET 7 AOT 的使用以及 .NET 與 Go 互相調用

文章插圖
然后在代碼中使用:
static void Main(){var result = Native.Add(1, 2);Console.WriteLine($"1 + 2 = {result}");Console.ReadKey();}在 Visual Studio 里啟動 Debug 調試:
.NET 7 AOT 的使用以及 .NET 與 Go 互相調用

文章插圖
可以看到,是正常運行的 。
接著,將 CsharpAot 項目發布為 AOT 后,再次執行:
.NET 7 AOT 的使用以及 .NET 與 Go 互相調用

文章插圖
可以看到,.NET AOT 調用 .NET AOT 的代碼是沒有問題的 。
Golang 部分Go 生成 Windows 動態鏈接庫,需要安裝 GCC,通過 GCC 編譯代碼生成對應平臺的文件 。
安裝 GCC需要安裝 GCC 10.3,如果 GCC 版本太新,會導致編譯 Go 代碼失敗 。
打開 tdm-gcc 官網,通過此工具安裝 GCC,官網地址:
https://jmeubank.github.io/tdm-gcc/download/
.NET 7 AOT 的使用以及 .NET 與 Go 互相調用

文章插圖
下載后,根據提示安裝 。
.NET 7 AOT 的使用以及 .NET 與 Go 互相調用

文章插圖
然后添加環境變量:
D:\TDM-GCC-64\bin
.NET 7 AOT 的使用以及 .NET 與 Go 互相調用

文章插圖
運行 gcc -v,檢查是否安裝成功 , 以及版本是否正確 。
.NET 7 AOT 的使用以及 .NET 與 Go 互相調用

文章插圖
Golang 導出函數本節的知識點是 cgo , 讀者可以從這里了解更多:
https://www.programmerall.com/article/11511112290/
新建一個 Go 項目:
.NET 7 AOT 的使用以及 .NET 與 Go 互相調用

文章插圖
新建一個 main.go 文件 , 文件內容如下:
package mainimport ( "fmt")import "C"http://export Startfunc Start(arg string) { fmt.Println(arg)}// 沒用處func main() {}在 Golang 中 , 要導出此文件中的函數,需要加上 import "C",并且 import "C" 需要使用獨立一行放置 。
//export {函數名稱} 表示要導出的函數,注意,//export 之間 沒有空格 。
main.go 編譯為動態鏈接庫:
go build -ldflags "-s -w" -o main.dll -buildmode=c-shared main.go
.NET 7 AOT 的使用以及 .NET 與 Go 互相調用

文章插圖
不得不說,Go 編譯出的文件 , 確實比 .NETAOT 小一些 。
前面,筆者演示了 .NET AOT 調用 .NET AOT,那么,Go 調用 Go 是否可以呢?
答案是:不可以 。
因為 Go 編譯出來的 動態鏈接庫本身帶有 runtime,Go 調用 main.dll 時 ,會出現異常 。
具有情況可以通過 Go 官方倉庫的 Issue 了解:https://github.com/golang/go/issues/22192
這個時候,.NET 加 1 分 。
雖然 Go 不能調用 Go 的,但是 Go 可以調用 .NET 的 。在文章后面會介紹 。
雖然說 Go 不能調用自己,這里還是繼續補全代碼,進一步演示一下 。
Go 通過動態鏈接庫調用函數的示例:
func main() { maindll := syscall.NewLazyDLL("main.dll") start := maindll.NewProc("Start") var v string = "測試代碼" var ptr uintptr = uintptr(unsafe.Pointer(&v)) start.Call(ptr)}代碼執行后會報錯:
.NET 7 AOT 的使用以及 .NET 與 Go 互相調用

文章插圖
.NET C# 和 Golang 互調C# 調用 Golang將 main.dll 文件復制放到 CsharpAot 項目中,設置 始終復制 。
.NET 7 AOT 的使用以及 .NET 與 Go 互相調用

文章插圖
然后在 Native 中添加以下代碼:
[LibraryImport("main.dll", SetLastError = true)]internal static partial void Start(IntPtr arg);
.NET 7 AOT 的使用以及 .NET 與 Go 互相調用

文章插圖
調用 main.dll 中的函數:
static void Main(){string arg = "讓 Go 跑起來";// 將申請非托管內存string轉換為指針IntPtr concatPointer = Marshal.StringToHGlobalAnsi(arg);Native.Start(concatPointer);Console.ReadKey();}

推薦閱讀