problem with GCHandle.alloc()
this is my structure:
[StructLayout(LayoutKind.Sequential,Pack=4)]
struct TMN_REPARSE_DATA_BUFFER
{
public uint ReparseTag;
public short ReparseDataLength;
public short Reserved;
public short SubstituteNameOffset;
public short SubstituteNameLength;
public short PrintNameOffset;
public short PrintNameLength;
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=1)]
public string PathBuffer;
};
I try to allocate pinned memory with GCHandle.Alloc() but get an error message saying my structure is not blittable.After investigating it seems the problem comes from the string parameter.
I don't understand what to do. String is a primitive type. What is the problem?
thank you
Hi,
System.String is actually not a blittable type. The blittable types are ones which have the same representation in both managed and unmanaged code. This includes Byte, SByte, Int*, UInt*, IntPtr, UIntPtr, Single, and Double. It also includes structures composed of only other blittable types.
The String class is not blittable for a few reasons
1. The String class contains data not found in a C-style string (such as the length and size of the internal buffer holding the string)
2. String is a reference type, not a value type. That means by directly pinning the structure down, you're only pinning a reference to the string, and not the string itself.
Also, since Strings can contain embedded null characters, while C-style strings cannot, you would have a problem marshaling any of those directly.
-Shawn
Well obviously your Marshaling doesnt do the job, my best guess is try to use some other marshaling of your string by looking at UnmanagedType enum.
Try first UnamangedType.LPWstr, since the chars in the string are 2byte UNICODE in the .net framework.
Also the SizeConst might cause you a problem somehow.
Marshalling is actually never coming into play here. When you pin a structure, what you're doing is telling the GC that it should not move the structure around in the managed heap. This allows you to pass the address of the structure on the heap directly to unmanaged code.
When you marshal a structure, a different operation occurs. Marshaling creates a new copy of the structure in unmanaged memory, which is suitable to pass to unmanaged code.
Obviously pinning is more efficient, since it doesn't require that a copy of the structure be made. However, the downside is that any structure that you pin must have the exact same layout in the unmanaged world as it does in the managed side of things. Since there is no copying, there's no chance for any translation to be done.
Since String does not have the same representation in both places, it needs to be marshaled, so that the marshaler can translate from a managed string into a form suitable for use in umanaged code.
Does that help to clear things up?
-Shawn