.NET 8 委托* 非托管抛出致命错误

问题描述 投票:0回答:1

我尝试调用手动映射的 AOT 编译的 .NET dll。 当我创建函数指针委托并调用它时,它会抛出异常“致命错误。无效程序:尝试从托管代码调用 UnmanagedCallersOnly 方法。”

  [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    private delegate long AddNumbersDelegate(int a, int b);
    public static void Main()
    {            
      
        Memory Dll = new Memory(File.ReadAllBytes(@"C:\VsProjects\ClassLibrary1\bin\Release\net8.0\publish\win-x64\ClassLibrary1.dll"));           
        AddNumbersDelegate delegat = (AddNumbersDelegate)Dll.GetDelegateFromFuncName("Sum", typeof(AddNumbersDelegate));

        long val = delegat(40, 2); //fatal error Invalid Program: attempted to call a UnmanagedCallersOnly method from managed code.\ works when AOT-compiled and .net framework 4.8
        
        Console.WriteLine("sum result:" + val);

        Console.ReadKey();
    }

   public static void Main()
   {
       Memory Dll = new Memory(File.ReadAllBytes(@"C:\VsProjects\ClassLibrary1\bin\Release\net8.0\publish\win-x64\ClassLibrary1.dll"));
       IntPtr ptr = (IntPtr)Dll.GetPtrFromFuncName("Sum");

       delegate* unmanaged[Cdecl]<int, int, long> delegat = (delegate* unmanaged[Cdecl]<int, int, long>)ptr;

       long val = delegat(40, 2); //fatal error Invalid Program: attempted to call a UnmanagedCallersOnly method from managed code. \ works when AOT-compiled

       Console.WriteLine("sum result:" + val);

       Console.ReadKey();
   }

Dll(AOT 编译):

 public class Class1
 {
     [UnmanagedCallersOnly(EntryPoint = "Sum", CallConvs = new[] { typeof(CallConvCdecl)})]
     public static long Sum(int a, int b)
     {
         return a + b;
     }

 }

调用函数指针100%有效。

我尝试了很多不同的方法来解决它:

  • 更改通话转换
  • CallConvSuppressGCTransition
  • 不同类型的代表。

当我使用 .net Framework 4.8 或 AOT 编译的 .net 8 exe 中的相同代码调用它时,它可以工作,但当我尝试从默认编译的 .net 8 代码调用时,它会抛出错误。调试或发布无关紧要。当我尝试使用 DllImport 或 LoadLibrary+GetProcAddress 调用它时,它也适用于 .NET 8。

c# .net unmanaged unmanaged-memory native-aot
1个回答
0
投票

所以我找到了解决方案,但我不建议像我一样这样做:

使用 x64dbg 探索我的进程,我发现这个错误是由 AOT Dll 引发的。这是我调用的函数ASM Sum func

如果我用 nops 替换这个调用指令,它将按预期返回 2 int 的总和。 其他解决方案是按照此调用并找到第一个 JNE 指令,然后用 JE 修补它 ASM security function

© www.soinside.com 2019 - 2024. All rights reserved.