fix(abcip): stride user-string arrays by the read buffer, not the built-in STRING size
Live read-only check against a production CompactLogix press: Program:UN01_Press._ModeNames (STR0016[32], 4 elements requested) returned an 80-byte buffer with libplctag.NET 1.5.2's ElementSize unset. The driver fell back to the static 88-byte STRING stride, read element 1 past the buffer, and the whole read failed (ErrorOutOfBounds -> BadCommunicationError). When the buffer divides evenly by the element count, that quotient is now the stride; the read returns [undefined, Production, Maintenance, Manual] as the controller holds.
This commit is contained in:
@@ -79,8 +79,7 @@ internal sealed class LibplctagTagRuntime : IAbCipTagRuntime
|
||||
// accounts for STRING capacity + atomic widths. ElementSize is int? on the wrapper — fall
|
||||
// back to a static size table when it is null/<=0 (e.g. a zero-length read) so the stride
|
||||
// is never 0.
|
||||
var elementSize = _tag.ElementSize ?? 0;
|
||||
var stride = elementSize > 0 ? elementSize : ElementByteSize(type);
|
||||
var stride = ResolveArrayStride(_tag.ElementSize, _tag.GetSize(), count, type);
|
||||
|
||||
return type switch
|
||||
{
|
||||
@@ -99,6 +98,26 @@ internal sealed class LibplctagTagRuntime : IAbCipTagRuntime
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Byte stride between array elements. libplctag's <c>ElementSize</c> wins when populated, but
|
||||
/// after a read it is <c>null</c> (observed live, libplctag.NET 1.5.2) — and the static table
|
||||
/// assumes the built-in 88-byte STRING, which is wrong for a user string type: a <c>STR0016</c>
|
||||
/// element is 20 bytes, so element 1 was read at offset 88 of an 80-byte buffer and the whole
|
||||
/// read failed. When the read buffer divides evenly by the element count, that quotient IS the
|
||||
/// element size, so it is used before the static table.
|
||||
/// </summary>
|
||||
/// <param name="elementSize">libplctag's reported element size, if any.</param>
|
||||
/// <param name="bufferSize">Bytes in the read buffer.</param>
|
||||
/// <param name="count">Element count requested.</param>
|
||||
/// <param name="type">Element type.</param>
|
||||
/// <returns>The stride in bytes.</returns>
|
||||
internal static int ResolveArrayStride(int? elementSize, int bufferSize, int count, AbCipDataType type)
|
||||
{
|
||||
if (elementSize is > 0) return elementSize.Value;
|
||||
if (count > 0 && bufferSize > 0 && bufferSize % count == 0) return bufferSize / count;
|
||||
return ElementByteSize(type);
|
||||
}
|
||||
|
||||
private bool[] BuildBoolArray(int count)
|
||||
{
|
||||
var arr = new bool[count];
|
||||
|
||||
Reference in New Issue
Block a user