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);
您好,我有一个 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);