使用.NET9开发AOT发布的类库,供其他开发工具调用
引言
.NET的AOT技术已日渐成熟,今天尝试使用.NET9.0开发DLL类库,通过AOT方式发布以后不需要安装.NET运行库,以方便其他开发工具调用。
初步测试
1、在VS2022中创建类库项目

一直直接下一步创建项目即可。
2、手工修改项目配置文件,增加支持AOT发布
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PublishAot>true</PublishAot>
</PropertyGroup>
3、添加导出函数
导出函数使用非托管调用者的属性声明(默认的调用约定应该是Windows DLL常用的“__stdcall”)
[UnmanagedCallersOnly(EntryPoint = "Add")]
public static int Add(int a, int b) { return a + b; }
4、发布
.NET9已支持Windows平台上的x86环境发布了:

发布后生成类库文件“ClassLibrary01.dll”以及PDB符号文件,文件大小只有4KB。
此时,导出的(C格式)函数只有“Add”这一个,DLL的文件依赖已经没有.NET运行库了:

5、在其他开发工具调用DLL函数
比如Delphi:
// 声明函数原型:
function Add(x: Integer; y: Integer): Integer; stdcall; external 'ClassLibrary01.dll' delayed;
// 调用:
ShowMessage(Format('DLL.Add返回:%d', [Add(5,6)]));
编译,将刚才生成的DLL文件复制过来,运行得到正确的结果:

32位Win7运行正常:

WinXP运行失败,提示没有bcrypt.dll,这个文件在Win7是自带的,把文件复制过来又提示另一个错误,看来是内部调用了XP没有的API了,那就可以不管WinXP了。。。


进一步测试
6、增加调用其他nuget类库的测试
用常用的类库“Newtonsoft.Json”试试吧,在项目的nuget包管理中安装:

修改类库源代码,增加两个导出函数试试:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
[JsonSerializable(typeof(Person))] // 每个用序列化的对象都要指明
[JsonSourceGenerationOptions(WriteIndented = true)]
internal partial class SourceGenerationContext : JsonSerializerContext
{
}
public static class Class1
{
[UnmanagedCallersOnly(EntryPoint = "Add")]
public static int Add(int a, int b) { return a + b; }
public static int Net_Add(int a, int b) { return a + b; }
[UnmanagedCallersOnly(EntryPoint = "JsonTest")]
public static IntPtr JsonTest()
{
var person = new Person
{
Name = "John",
Age = 30
};
// JsonConvert.SerializeObject(person); 返回空白json,这个习惯用法不能用!
string json = System.Text.Json.JsonSerializer.Serialize(person, SourceGenerationContext.Default.Person);
return Marshal.StringToHGlobalUni(json); // string对象转wchar_t *
}
}
重新发布,DLL文件变为1.65MB。
这是导出的函数(可以看到,如果没指定非托管调用者的属性,名字就不是按照C的格式导出):

修改调用类库的应用代码:
function Add(x: Integer; y: Integer): Integer; stdcall; external 'ClassLibrary01.dll' delayed;
function JsonTest(): PChar; stdcall; external 'ClassLibrary01.dll' delayed;
ShowMessage(Format('DLL.JsonTest 返回:%s', [JsonTest()]));
运行得到正确的结果:

初步结论
去年年底发布的.NET9.0,完善了对32位系统的支持,Windows平台可以用x86了,这是向完善又迈进了一大步,可以考虑逐渐取代过去我用C++实现的大量工作了。


浙公网安备 33010602011771号