使用.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++实现的大量工作了。

 

posted @ 2025-04-01 15:08  decode-dev  阅读(699)  评论(2)    收藏  举报