It turns out idea to use records in ADS client instead of structs wasn’t a good idea. I expected some issues, mostly with lack of parameterless constructor, but things turned out worse than expected.
let’s consider simple struct example
[<StructLayout(LayoutKind.Sequential, Pack=1)>] type SimpleStruct = struct val byteVar: BYTE end [<StructLayout(LayoutKind.Sequential, Pack=1)>] type ContainingStruct = struct [<field: MarshalAs(UnmanagedType.Struct)>] val nested: SimpleStruct end [<StructLayout(LayoutKind.Sequential, Pack=1)>] type ContainingStructArray = struct [<field: MarshalAs(UnmanagedType.ByValArray, SizeConst=10,ArraySubType=UnmanagedType.Struct)>] val nested: SimpleStruct array end Assert.Equal(1, typedefof<SimpleStruct> |> Marshal.SizeOf) Assert.Equal(1, typedefof<ContainingStruct> |> Marshal.SizeOf) Assert.Equal(10, typedefof<ContainingStructArray> |> Marshal.SizeOf)
all passes like a charm, now let’s rewrite our structs to records
[<StructLayout(LayoutKind.Sequential, Pack=1)>] type SimpleRecord = { byteVar: BYTE } [<StructLayout(LayoutKind.Sequential, Pack=1)>] type ContainingRecord = { [<field: MarshalAs(UnmanagedType.Struct)>] nested: SimpleRecord } [<StructLayout(LayoutKind.Sequential, Pack=1)>] type ContainingRecordArray = { [<field: MarshalAs(UnmanagedType.ByValArray, SizeConst=10,ArraySubType=UnmanagedType.Struct)>] nested: SimpleRecord array } Assert.Equal(1, typedefof<SimpleRecord> |> Marshal.SizeOf) //success Assert.Equal(1, typedefof<ContainingRecord> |> Marshal.SizeOf) //success Assert.Equal(10, typedefof<ContainingRecordArray> |> Marshal.SizeOf) //failure, actual size is 40
note that it only doesn’t work on array of structs, not sure how it works under the hood, but somehow it always defaults to 4 bytes, as if we used sizeof<SimpleRecord>, thus array of 10 items, each of them 4 bytes.
Solution?
I’m aware of none yet, beside writing custom code to serialize/deserialize records to/from byte arrays. Which itself would be that bad idea (if we ignore performance) as I could handle endianness conversions if by any chance communication with PLC would occur from big endian machine.
Recent Comments