c# ReadOnlyMemory 来自指针

c# ReadOnlyMemory from pointer

您好,我有一个 c 本机库,它以 char* 的形式返回 json。我想在 c# 中做的是使用此指针并将其直接写入

this.ControllerContext.HttpContext.Response.BodyWriter;

我能够从 ptr 创建 ReadOnlySpan,但据我所知,PipeWriter 只接受 ReadOnlyMemory<byte>,它没有来自 IntPtr 的构造函数。有没有一种方法可以从 IntPtr 创建 ReadOnlyMemory<byte> 或从本机库中编写我的字符串而无需额外复制一次?

也许使用这样的东西?

public class Utility
{
    public System.ReadOnlyMemory<T> ConvertToReadOnlyMemory(System.ReadOnlySpan<T> input) {
        var tmp = new System.Memory<T>();
        input.CopyTo(tmp.Span);
        return (System.ReadOnlyMemory<T>)tmp;
    }
}

但是,我认为这将涉及将流完全复制到堆存储中,这可能不是您想要的...

如果这可以加快速度并满足您的需求,我很高兴。

namespace Helper
{
    using System;
    using System.Runtime.InteropServices;

    public static class CStringMapper
    {
        // convert unmanaged c string to managed c# string
        public string toCSharpString(char* unmanaged_c_string)
        {
             return Marshal.PtrToStringAnsi((IntPtr)unmanaged_c_string);
         }

         // Free unmanaged c pointer
         public void free(char* unmanaged_c_string)
         {
             Marshal.FreeHGlobal((IntPtr)unmanaged_c_string);
         }
     }
}

用法:

 using Helper;

 /* generate your unmanaged c string here */

 try
 {
     // eg. char* OO7c = cLibFunc();
     string cSharpString = CStringMapper.toCSharpString(OO7c);
 } 
 finally
 {
     // Make sure to  freeing the pointer
     CStringMapper.free(OO7c);
 }

感谢您的回答,但其中 none 没有额外的副本。我终于弄明白了,所以如果有人遇到困难,这里是解决方案。

所以我能做到这一点的唯一方法就是。

 await Response.StartAsync(HttpContext.RequestAborted);
 var dest = Response.BodyWriter.GetMemory((int)jsonLen).Pin();
 unsafe { memcpy(dest.Pointer), srcPtr, srcLen); }
 Response.BodyWriter.Advance(srcLen);
 await Response.BodyWriter.FlushAsync(HttpContext.RequestAborted);