.NET 7 AOT 的使用以及 .NET 与 Go 互相调用( 二 )

[LibraryImport]
文档是这样介绍的:
Indicates that a source generator should create a function for marshalling arguments instead of relying on the runtime to generate an equivalent marshalling function at run time.指示源生成器应创建用于编组参数的函数,而不是依赖运行库在运行时生成等效的编组函数 。简单来说,就是我们要使用 AOT 写代码,然后代码中引用到别的动态链接库时,需要使用 [LibraryImport] 引入这些函数 。

笔者没有在 AOT 下测试过 [DllImport],读者感兴趣可以试试 。
新建两个结构体 MEMORYSTATUS.csMemoryStatusExE.cs
MEMORYSTATUS.cs
public struct MEMORYSTATUS{internal UInt32 dwLength;internal UInt32 dwMemoryLoad;internal UInt32 dwTotalPhys;internal UInt32 dwAvailPhys;internal UInt32 dwTotalPageFile;internal UInt32 dwAvailPageFile;internal UInt32 dwTotalVirtual;internal UInt32 dwAvailVirtual;}MemoryStatusExE.cs
public struct MemoryStatusExE{/// <summary>/// 结构的大小,以字节为单位,必须在调用 GlobalMemoryStatusEx 之前设置此成员 , 可以用 Init 方法提前处理/// </summary>/// <remarks>应当使用本对象提供的 Init,而不是使用构造函数!</remarks>internal UInt32 dwLength;/// <summary>/// 一个介于 0 和 100 之间的数字,用于指定正在使用的物理内存的大致百分比(0 表示没有内存使用,100 表示内存已满) 。/// </summary>internal UInt32 dwMemoryLoad;/// <summary>/// 实际物理内存量,以字节为单位/// </summary>internal UInt64 ullTotalPhys;/// <summary>/// 当前可用的物理内存量,以字节为单位 。这是可以立即重用而无需先将其内容写入磁盘的物理内存量 。它是备用列表、空闲列表和零列表的大小之和/// </summary>internal UInt64 ullAvailPhys;/// <summary>/// 系统或当前进程的当前已提交内存限制,以字节为单位,以较小者为准 。要获得系统范围的承诺内存限制,请调用GetPerformanceInfo/// </summary>internal UInt64 ullTotalPageFile;/// <summary>/// 当前进程可以提交的最大内存量 , 以字节为单位 。该值等于或小于系统范围的可用提交值 。要计算整个系统的可承诺值,调用GetPerformanceInfo核减价值CommitTotal从价值CommitLimit/// </summary>internal UInt64 ullAvailPageFile;/// <summary>/// 调用进程的虚拟地址空间的用户模式部分的大小 , 以字节为单位 。该值取决于进程类型、处理器类型和操作系统的配置 。例如,对于 x86 处理器上的大多数 32 位进程,此值约为 2 GB,对于在启用4 GB 调整的系统上运行的具有大地址感知能力的 32 位进程约为 3 GB。/// </summary>internal UInt64 ullTotalVirtual;/// <summary>/// 当前在调用进程的虚拟地址空间的用户模式部分中未保留和未提交的内存量,以字节为单位/// </summary>internal UInt64 ullAvailVirtual;/// <summary>/// 预订的 。该值始终为 0/// </summary>internal UInt64 ullAvailExtendedVirtual;internal void Refresh(){dwLength = checked((UInt32)Marshal.SizeOf(typeof(MemoryStatusExE)));}}定义引用库函数的入口:
public static partial class Native{/// <summary>/// 检索有关系统当前使用物理和虚拟内存的信息/// </summary>/// <param name="lpBuffer"></param>/// <returns></returns>[LibraryImport("Kernel32.dll", SetLastError = true)][return: MarshalAs(UnmanagedType.Bool)]internal static partial Boolean GlobalMemoryStatusEx(ref MemoryStatusExE lpBuffer);}然后调用 Kernel32.dll 中的函数:
public class Program{static void Main(){var result = GetValue();Console.WriteLine($"当前实际可用内存量:{result.ullAvailPhys / 1000 / 1000}MB");Console.ReadKey();}/// <exception cref="Win32Exception"></exception>public static MemoryStatusExE GetValue(){var memoryStatusEx = new MemoryStatusExE();// 重新初始化结构的大小memoryStatusEx.Refresh();// 刷新值if (!Native.GlobalMemoryStatusEx(ref memoryStatusEx)) throw new Win32Exception("无法获得内存信息");return memoryStatusEx;}}使用 AOT 发布项目 , 执行 CsharpAot.exe 文件 。
.NET 7 AOT 的使用以及 .NET 与 Go 互相调用

文章插图
减少体积在前面两个例子中可以看到 CsharpAot.exe 文件大约在 3MB 左右,但是这个文件还是太大了 , 那么我们如何进一步减少 AOT 文件的大小呢?
读者可以从这里了解如何裁剪程序:https://learn.microsoft.com/zh-cn/dotnet/core/deploying/trimming/trim-self-contained

推荐阅读