当前位置: 首页 > article >正文

使用AoT让.NetFramework4.7.2程序调用.Net8编写的库

1、创建.Net8的库,双击解决方案中的项目,修改如下,启用AoT:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Library</OutputType>
    <PublishAot>true</PublishAot>
    <IsAotCompatible>true</IsAotCompatible>
    <CopyRefAssembliesToPublishDirectory>true</CopyRefAssembliesToPublishDirectory>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
</Project>

在Class1.cs文件中加入如下代码:

using System.Runtime.InteropServices;

namespace AoT001
{
    public class Export
    {
        [UnmanagedCallersOnly(EntryPoint = "Add")]
        public static int Add(int a, int b)
        {
            return a + b;
        }

        [UnmanagedCallersOnly(EntryPoint = "Combine")]
        public static IntPtr Combine(IntPtr str, int num)
        {
            var name = nameof(Export);
            string? inputStr = Marshal.PtrToStringAnsi(str);
            string? result = $"{inputStr} -- {num} -- {name}";
            return Marshal.StringToHGlobalAnsi(result);
        }

        [UnmanagedCallersOnly(EntryPoint = "Free")]
        public static void Free(IntPtr ptr) 
        {
            Marshal.FreeHGlobal(ptr);
        }
    }
}

右键,AoT库项目, 发布,弹出如下图,按步骤配置:

注意:AoT仅支持win-x64

点击发布后,启动编译过程,结果如下图:

如图,简单的dll编译后size是1.3M,因为AoT将所有的依赖库都打包到了DLL内,没有C#运行环境也可以执行。使用Dependence查看如下图:

可见AoT编译的dll已经和C或C++编译的dll兼容。在Framework4.7.2项目中可按普通C编译的dll使用,如下:

namespace Winform472
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {
            var sum = AoTHelp.Add(1111, 1112);
            var str1 = "Hello World 0001";
            var ptr1 = Marshal.StringToHGlobalAnsi(str1);
            var ptr2 = AoTHelp.Combine(ptr1, 500);
            var str2 = Marshal.PtrToStringAnsi(ptr2);
            AoTHelp.Free(ptr2);
            MessageBox.Show($"Hello, World! {sum}  {str2}");
        }
    }


    public static class AoTHelp
    {
        [DllImport("AoT001.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
        public static extern int Add(int a, int b);

        [DllImport("AoT001.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
        public static extern IntPtr Combine(IntPtr str, int sum);

        [DllImport("AoT001.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
        public static extern void Free(IntPtr ptr);
    }
}

点击按钮界面如下:

在AoT库中引入MathNet.Numerics库,测试使用三方库后AoT创建dll的情况,新增函数:

        [UnmanagedCallersOnly(EntryPoint = "UseThirdLibTest")]
        public static bool UseThirdLibTest(int a, int b)
        {
            var D = Matrix<double>.Build.Dense(2, 9, 1);
            Console.WriteLine(D);
            return MathNet.Numerics.Control.Equals(a, b);
        }

重新发布后dll拷贝到调用项目的debug子命令,dll大下从1.3M变为1.8M。调用代码如下:

        [DllImport("AoT001.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
        public static extern bool UseThirdLibTest(int a, int b);


        private void button2_Click(object sender, EventArgs e)
        {
            var res = AoTHelp.UseThirdLibTest(100, 100);
            MessageBox.Show(res.ToString());
        }

AoT库中传递结构体,AoT定义及调用分别如下:

    [StructLayout(LayoutKind.Sequential, Pack = 8)]
    public struct ParamStruct
    {
        public Int32 ResFlag;
        public UInt32 a;
        public UInt32 b;
        public UInt32 c;
    }

        [UnmanagedCallersOnly(EntryPoint = "GetValueFromAoT")]
        public static ParamStruct GetValueFromAoT(int initValue, ParamStruct param)
        {
            var result = new ParamStruct();
            if (initValue < 0)
            {
                result.ResFlag = -1;
                return result;
            }
            result.ResFlag = 0;
            result.a = param.a + (UInt32)initValue;
            result.b = param.b + (UInt32)initValue * 2;
            result.c = param.c + (UInt32)initValue * 3;
            return result;
        }

 

    [StructLayout(LayoutKind.Sequential, Pack = 8)]
    public struct ParamStruct
    {
        public Int32 ResFlag;
        public UInt32 a;
        public UInt32 b;
        public UInt32 c;
    }
    public static class AoTHelp
    {
        [DllImport("AoT001.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
        public static extern ParamStruct GetValueFromAoT(int initValue, ParamStruct param);
    }



            var param = new ParamStruct { a = 10, b = 20, c = 30};
            var param2 = AoTHelp.GetValueFromAoT(100, param);
            MessageBox.Show(param2.ToString());

注:结构体定义内如含bool运行时报错、含数组编译报错,简单的数值类型是ok的。如需要传递字符串,可使用IntPtr来实现。


http://www.kler.cn/a/566048.html

相关文章:

  • Mac 中与PyCharm 中的单步调试快捷键
  • 【江科大STM32】TIM输出比较-PWM功能(学习笔记)
  • 【JS】Web Worker知识和动态创建以及场景案例
  • YOLOv8 行人相关识别技术提升
  • P3372 【模板】线段树 1
  • 自用的vim脚本
  • Springboot使用Milvus的基本操作
  • 基于Django的考研院校数据分析及推荐系统
  • cpp重写堆的比较函数
  • MapStruct 对象转换工具【DDD 架构】
  • 搭建gn环境踩坑存档
  • wzl-django学习
  • 大模型(DeepSeek),具身智能,VLA(pi0),机器人,全网资料总结。
  • 数据库MySQL,在终端输入后,提示不是内部命令等
  • 深入解析设备树(Device Tree)中的属性(Properties)
  • 【C++】Rusage(一)
  • HTTP~文件 MIME 类型
  • 深圳出版集团通过腾讯云接入DeepSeek,用于智能问答、客户服务、活动策划等场景
  • 使用 Selenium 和 Requests 自动化获取动态 Referer 和 Sign 的完整指南
  • 论文阅读《 FEDERATED RECOMMENDATION WITH ADDITIVE PERSONALIZATION》