问题
I'm trying to marshal a dynamically allocated char array in a struct to C#. The struct has a pointer to the array. The problem is the char array contains multiple null terminated strings and the last string is terminated by two consecutive null chars.
If I try to marshal it as LPStr
I will get only de first string in the "list".
I tried using UnmanagedMemoryStream but it requires to know the length of the array.
Is there a way to read the bytes as a stream without knowing the length of the array? (Aside from using a n length byte buffer and keep increasing the pointer until two consecutive null terminating chars are found).
回答1:
As suggested by Hans Passant, the only way is to Marshal.ReadByte()
, so in the end you have to read the memory multiple times (PtrToStringAnsi
reads it at least twice plus the one we do to find where the next string begins).
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();
}
回答2:
An alternate version, which avoids a second sweep over the array
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();
}
来源:https://stackoverflow.com/questions/51218293/how-to-marshal-an-unknown-length-c-string-to-c-sharp-using-its-pointer