.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 中 , 出现了新的操作方式

推荐阅读