1

When marshalling struct which contains a single char field from C++ to C# how the C# struct definition should look like?

[StructLayout(LayoutKind.Sequential, Size = 1), Serializable]
public struct SomeStruct
{
    [MarshalAs(UnmanagedType.I1)]
    public sbyte Field;
}

or

[StructLayout(LayoutKind.Sequential, Size = 1), Serializable]
public struct SomeStruct
{
    [MarshalAs(UnmanagedType.U1)]
    public byte Field;
}

I can't find a clear info about should it be a signed byte or not. (It is declared as 'char' in C++ struct definition)

UPD: Does It depends on whether C++ lib was build with GCC or VS (default compiler options)? If not, can I hope 'char' is signed on both GCC and VS (default compiler options)

illegal-immigrant
  • 8,089
  • 9
  • 51
  • 84

3 Answers3

3

In Visual Studio and GCC, char is signed by default. The /J compiler option (-funsigned-char for GCC) can be used to make it unsigned.

So the answer depends on whether or not that option is used in your C++ project.

Community
  • 1
  • 1
Frédéric Hamidi
  • 258,201
  • 41
  • 486
  • 479
3

You can't, in general, tell if char is signed or unsigned in C++. It depends on the implementation, and a single compiler (implementation) can often be configured through options to make it either way.

The best choice would be to make it explicit in the C++ code if possible, i.e. use signed char or unsigned char. Then you can pick sbyte or byte for the C# marshalling as appropriate.

unwind
  • 391,730
  • 64
  • 469
  • 606
1

The answer depends on how you prefer to store the value in C#. You should choose whichever is most convenient.

  • If you store it in your C# variable as an unsigned value, then marshal it as UnmanagedType.U1.
  • If you store it in your C# variable as a signed value, then marshal it as UnmanagedType.I1.

The point being that once that byte crosses the module boundary it's the bitwise representation that matters and not the logical representation in the C# code. An unsigned value of 255 is equivalent to a signed value of -1 once you have reached the C++ code.


Of course, this assumes that you are using char as a character type. In a comment to the question you state that you are using it as a integer type, in which case you need to decide whether or not it is signed and marshal accordingly.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490