Interop Structure: Should Unsigned Short be Mapped to byte[]?
I have such a C++ structure:
typedef struct _FILE_OP_BLOCK
{
unsigned short fid; // objective file ID
unsigned short offset; // operating offset
unsigned char len; // buffer length(update)
// read length(read)
unsigned char buff[240];
} FILE_OP_BLOCK;
And now I want to map it in .Net. The tricky thing is that the I should pass a 2 byte array for fid
, and integer for len
, even though in C# fid
is an unsigned short
and len
is an unsigned char
I wonder whether my structure ( in C#) below is correct?
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharS开发者_运维技巧et.Auto)]
public struct File_OP_Block
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public byte[] fid;
public ushort offset;
public byte length;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 240)]
public char[] buff;
}
Your CharSet property on the [DllImport] attribute is definitely wrong, you need CharSet.Ansi to get the P/Invoke marshaller to convert it to a char[]. Declare the buff member as a string for easier usage. While declaring the fid member as a byte[] isn't wrong, I really don't see the point of it. That the unmanaged code copies a char[] into it is an implementation detail. Thus:
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public struct File_OP_Block
{
public ushort fid;
public ushort offset;
public byte length;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 240)]
public string buff;
}
Given that the C++ short
data type is actually two bytes, a two byte array should work. The integer sizes in C/C++ are not strictly defined, so the standard only says that a short
is at least two bytes.
The C# char
data type is a 16 bit unicode character, so that doesn't match the C++ char
data type which is an 8 bit data type. You either need an attribute to specify how the characters are encoded into bytes, or use a byte array.
You might need an attribute to specify the packing, so that there is no padding between the members.
精彩评论