如何使用其指针将未知长度的 C++ 字符串编组为 C#?
How to marshal an unknown length C++ string to C# using its pointer?
我正在尝试将结构中动态分配的 char 数组编组到 C#。该结构有一个指向数组的指针。问题是 char 数组包含多个以空字符结尾的字符串,最后一个字符串以两个连续的空字符结尾。
如果我尝试将其编组为 LPStr
,我只会得到 "list" 中的第一个字符串。
我尝试使用 UnmanagedMemoryStream,但它需要知道数组的长度。
有没有办法在不知道数组长度的情况下将字节作为流读取? (除了使用 n 长度字节缓冲区并继续增加指针直到找到两个连续的空终止字符)。
正如Hans Passant所建议的那样,唯一的办法就是Marshal.ReadByte()
,所以最后你必须多次读取内存(PtrToStringAnsi
至少读取两次加上我们所做的一次找到下一个字符串的开始位置)。
public static string[] IntPtrToStringArrayAnsi(IntPtr ptr)
{
var lst = new List<string>();
do
{
lst.Add(Marshal.PtrToStringAnsi(ptr));
while (Marshal.ReadByte(ptr) != 0)
{
ptr = IntPtr.Add(ptr, 1);
}
ptr = IntPtr.Add(ptr, 1);
}
while (Marshal.ReadByte(ptr) != 0);
// See comment of @zneak
if (lst.Count == 1 && lst[0] == string.Empty)
{
return new string[0];
}
return lst.ToArray();
}
替代版本,避免对数组进行第二次扫描
private static List<string> IntPtrToStringArrayAnsi(IntPtr ptr)
{
var lst = new List<string>();
while (true)
{
var str = Marshal.PtrToStringAnsi(ptr);
if (!string.IsNullOrEmpty(str))
{
lst.Add(str);
ptr += str.Length + 1;
}
else
break;
}
return lst.ToArray();
}
我正在尝试将结构中动态分配的 char 数组编组到 C#。该结构有一个指向数组的指针。问题是 char 数组包含多个以空字符结尾的字符串,最后一个字符串以两个连续的空字符结尾。
如果我尝试将其编组为 LPStr
,我只会得到 "list" 中的第一个字符串。
我尝试使用 UnmanagedMemoryStream,但它需要知道数组的长度。
有没有办法在不知道数组长度的情况下将字节作为流读取? (除了使用 n 长度字节缓冲区并继续增加指针直到找到两个连续的空终止字符)。
正如Hans Passant所建议的那样,唯一的办法就是Marshal.ReadByte()
,所以最后你必须多次读取内存(PtrToStringAnsi
至少读取两次加上我们所做的一次找到下一个字符串的开始位置)。
public static string[] IntPtrToStringArrayAnsi(IntPtr ptr)
{
var lst = new List<string>();
do
{
lst.Add(Marshal.PtrToStringAnsi(ptr));
while (Marshal.ReadByte(ptr) != 0)
{
ptr = IntPtr.Add(ptr, 1);
}
ptr = IntPtr.Add(ptr, 1);
}
while (Marshal.ReadByte(ptr) != 0);
// See comment of @zneak
if (lst.Count == 1 && lst[0] == string.Empty)
{
return new string[0];
}
return lst.ToArray();
}
替代版本,避免对数组进行第二次扫描
private static List<string> IntPtrToStringArrayAnsi(IntPtr ptr)
{
var lst = new List<string>();
while (true)
{
var str = Marshal.PtrToStringAnsi(ptr);
if (!string.IsNullOrEmpty(str))
{
lst.Add(str);
ptr += str.Length + 1;
}
else
break;
}
return lst.ToArray();
}