c# ReadOnlyMemory из указателя - PullRequest
       37

c# ReadOnlyMemory из указателя

0 голосов
/ 12 марта 2020

Привет, у меня есть c нативная библиотека, которая возвращает мне json как char *. В c# я бы хотел использовать этот указатель и записать его прямо в

this.ControllerContext.HttpContext.Response.BodyWriter;

. Я могу создать ReadOnlySpan из ptr, но, насколько я могу судить, PipeWriter принимает только ReadOnlyMemory<byte>, который не имеет конструктора из IntPtr. Есть ли способ создать ReadOnlyMemory<byte> из IntPtr или каким-либо другим способом записать мою строку из нативной библиотеки без дополнительного ее копирования?

Ответы [ 3 ]

1 голос
/ 16 марта 2020

Спасибо за ваши ответы, но ни один из них не был без дополнительной копии. Я наконец-то понял это, поэтому в случае, если кто-то с этим борется, вот решение.

Так что единственный способ, которым я могу достичь этого, - это как.

 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);
0 голосов
/ 12 марта 2020

Я рад, если это может ускорить и соответствовать тому, что вы хотите.

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);
 }
0 голосов
/ 12 марта 2020

Может быть, использовать что-то вроде этого?

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;
    }
}

Однако я думаю, что это будет включать в себя полное копирование потока в кучное хранилище, что, вероятно, не то, что вы хотите ...

...