Closed drvic10k closed 2 years ago
interestingly, this problem disappears, when the bool
is changed to byte
but byte
is still interpreted as bool
(not sure, but this might be the problem on the powershell script side)
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi, Pack = 1)]
public class MyStruct
{
public MyStruct(byte a, short b, int c)
{
this.a = a;
this.b = b;
this.c = c;
}
[FieldOffset(1)]
public short b;
[FieldOffset(3)]
public int c;
[FieldOffset(0)]
public byte a;
}
_symbolValues.Add(this.Symbols["Main.myStruct1"], new MyStruct(1, 260, 300));
There is a second place where the order of the fields have to be changed. In the symbolic definition of the MyStruct datatype. Look for the "AddMember" statements in the demo server code. Beneath of that, your FieldOffset statements are now wrong. You have to align the data properly in memory.
another test case:
make the struct definition match the order of fields:
StructType dtStruct = new StructType("MYSTRUCT", null)
// Add Members
.AddAligned(new Member("b", dtInt))
.AddAligned(new Member("c", dtDInt))
.AddAligned(new Member("a", dtBool))
;
that means, that these 3 things need to be in sync:
I expected the numbers 2 and 3 to need to match, but number 1 seems strange
is that really the case?
StructType dtStruct = new StructType("MYSTRUCT", null)
// Add Members
.AddAligned(new Member("b", dtInt)) // Field-Offset 0
.AddAligned(new Member("c", dtDInt)) // Field-Offset 2
.AddAligned(new Member("a", dtBool)) // Field-Offset 6
;
If you order your type like that you have (because the FieldOffset is calculated by AddAligned internally);
(Field)Offset 0: b (2 Bytes)
(Field)Offset 2: c (4 Bytes)
(Field)Offset 6: a (1 Byte)
Without having tested it yet, in my opinion the Default-Marshaler should work with both cases below:
[FieldOffset(0)]
public short b;
[FieldOffset(2)]
public int c;
[FieldOffset(6)]
public bool a;
or
[FieldOffset(6)]
public bool a;
[FieldOffset(0)]
public short b;
[FieldOffset(2)]
public int c;
Relevant is only the correct FieldOffset for the Memory alignment - not the order.
it works as you describe with byte
it fails with bool
Seems right. For struct types the .NET Interop Default marshaler is used. That means that the boolean is marshalled with 4-bytes by default, see here:
The example defines the type 'dtBool' as size '1' (1-Byte). Therefore there is a misalignment in the FieldOffsets. I'll correct the example in forcing the .NET marshaler to use UnmanagedType.U1 for the boolean.
See also: https://docs.microsoft.com/en-us/dotnet/standard/native-interop/customize-struct-marshalling
great, I tried that and it works
The order in which the fields are defined has influence on the values
Steps too reproduce: take the sample and move the
bool a
field in theMyStruct
down (keep the attribute value)now when getting the MyStruct value from server, you get different values
_symbolValues.Add(this.Symbols["Globals.myStruct1"], new MyStruct(true,42,99));
_symbolValues.Add(this.Symbols["Main.myStruct1"], new MyStruct(true, 260, 300));