开发者

Marshal.PtrToStructure marshaled string is empty

I'm trying to marshal a struct from a byte[]. Each part works except marshaling a string. It looks to me like a BSTR:

06 00 00 00 48 00 65 00 6c 00 6c 00 6f 00 21 00 00 00

So, that's a 4-byte length then "Hello!" in unicode with a double null terminator. Here's the marshaling code I have toyed with:

string auto = Marshal.PtrToStringAuto(nextSchedulePtr); // returns "Hello!"
string ansi = Marshal.PtrToStringAnsi(nextSchedulePtr); // returns "H"
string uni = Marshal.PtrToStringUni(nextSchedulePtr);   // returns "Hello!"
string bstr开发者_运维知识库 = Marshal.PtrToStringBSTR(nextSchedulePtr); // returns "Hel"
Schedule schedule = (Schedule)Marshal.PtrToStructure(nextSchedulePtr, typeof(Schedule)); // returns "" with UnmanagedType.BStr and UnmanagedType.LPWStr

Method 1 calls method 3 anyway, so this makes sense. However, I can't specify any type within the [MarshalAs(UnmanagedType.X)] attribute that will allow the structure to return anything meaningful whatsoever.

I have pared down the structure to this:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct Schedule 
{
    [MarshalAs(UnmanagedType.BStr)]
    public string Name;
}

I've literally tried all of the valid values for UnmanagedType.X and they either throw AccessViolationExceptions or return an empty string or return junk. None returns "Hello!". Am I not able to load this data into a struct?

Note: I cannot change the data, it is set in stone. I can, however, change my code. I have also pinned the byte[] so it is not being GC'ed.


The problem is that the Schedule struct you are defining matches this kind of C struct:

struct Schedule {
    BSTR *Name;
};

While the structure that exists in memory at the IntPtr you are tinkering with has the layout:

struct Schedule {
    BSTR Name;
};

If you use Marshal.StructureToPtr() on an instance of Schedule and then inspect the memory, you will see that only the first four bytes get set, because they are a pointer.

Unfortunately, there is no elegant workaround to this in .NET. You cannot use a non-pointer string in a struct because then the struct would be of variable length.

If it is an option, forgo the struct entirely and stick with Marshal.PtrToStringAuto().

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜