Send mail to the author(s)

August 22, 2007

HOWTO: Marshal fixed-length strings

On Monday I got an internal question about marshaling fixed-length strings between managed and native code. The scenario is you have a native struct with a member defined something like this:

typedef struct SOME_STRUCT {
    DWORD size;
    TCHAR entryName[20];
}

How can you marshal the TCHAR string in managed code? You marshal it as a UnmanagedType.ByValTStr and specify the size like this:

[StructLayout(LayoutKind.Sequential)]
public struct SomeStruct
{
    public int Size;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
    public string EntryName;
}

The documentation for UnmanagedType.ByValTStr describes it as "a fixed-length array of characters; the array's type is determined by the character set of the containing structure".

On the other hand, if the native struct is defined like this:

typedef struct SOME_STRUCT {
    DWORD size;
    TCHAR *entryName;
}

You would marshal the TCHAR pointer as a UnmanagedType.LPTStr like this:

[StructLayout(LayoutKind.Sequential)]
public struct SomeStruct
{
    public int Size;
    [MarshalAs(UnmanagedType.LPTStr)]
    public string EntryName;
}