You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Native AOT中如何将string作为UnmanagedCallersOnly方法的返回类型?

Native AOT中UnmanagedCallersOnly方法返回string报错的问题

我是Native AOT新手,近期跟随教程实操,教程代码如下:

using System.Runtime.InteropServices;

namespace ClassLibrary1
{
    public class Class1
    {
        [UnmanagedCallersOnly(EntryPoint = "Add")]
        public static int Add(int a, int b) => a + b;
    }
}

该代码运行正常。现在我希望让带有[UnmanagedCallersOnly]特性的方法返回string,编写了如下代码:

[UnmanagedCallersOnly(EntryPoint = "Test")]
public static string Test()
{
    return "Test";
}

但VS报错:

Cannot use 'string' as a return type on a method attributed with
'UnmanagedCallersOnly'.

请问问题出在哪里?如何在Native AOT中实现返回string?


问题原因

[UnmanagedCallersOnly]修饰的方法是供非托管代码调用的,要求返回类型必须是能直接映射到非托管环境的类型。C#的string是托管类型,依赖CLR的内存管理机制,非托管代码无法直接识别和处理这种内存结构,因此编译器禁止直接返回string。

解决方法

要实现向非托管代码返回字符串,需要采用非托管友好的内存交互方式,以下是两种常用方案:

方案1:返回UTF-8编码的非托管指针

使用Marshal.StringToCoTaskMemUTF8将托管字符串转换为非托管内存中的UTF-8字节数组,返回其指针。注意非托管调用方需要调用CoTaskMemFree释放这块内存,避免内存泄漏。

using System.Runtime.InteropServices;

[UnmanagedCallersOnly(EntryPoint = "Test")]
public static IntPtr Test()
{
    string managedStr = "Test";
    return Marshal.StringToCoTaskMemUTF8(managedStr);
}

方案2:让调用方提供缓冲区

由非托管代码提前分配好缓冲区,将缓冲区指针和大小传入方法,方法把字符串写入缓冲区。这种方式不需要返回内存,避免了内存泄漏风险,适合需要重复使用缓冲区的场景。

using System.Runtime.InteropServices;
using System.Text;

[UnmanagedCallersOnly(EntryPoint = "Test")]
public static int Test(IntPtr buffer, int bufferSize)
{
    string managedStr = "Test";
    byte[] strBytes = Encoding.UTF8.GetBytes(managedStr);
    // 缓冲区不足时,返回需要的字节数(包含终止符)
    if (bufferSize < strBytes.Length + 1)
    {
        return strBytes.Length + 1;
    }
    // 将字符串写入缓冲区并添加终止符
    Marshal.Copy(strBytes, 0, buffer, strBytes.Length);
    Marshal.WriteByte(buffer, strBytes.Length, 0);
    return 0; // 写入成功返回0
}

内容的提问来源于stack exchange,提问作者Melon NG

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 16:12:43