You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Netlogix 7.0如何读取带长度的UDT标签并解析为结构体数组?

解决方案

首先需要确保结构体的内存布局和PLC中的存储对齐规则一致,先修正结构体定义:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct STRUCT_A
{
    public bool Active;
    public int Value;
}

读取PLC标签并转换为结构体数组

方式一:使用Marshal内存转换(适配PLC内存布局完全匹配的场景)

// 初始化PLC连接(以EthernetIP为例,根据你的INGEAR驱动类型调整)
var plc = new EthernetIPClient("PLC_IP_ADDRESS");
plc.Connect();

// 读取标签的原始字节数组
byte[] rawBytes = plc.Read(MyTags);

// 转换为STRUCT_A数组
STRUCT_A[] structArray = ConvertBytesToStructArray(rawBytes);

// 遍历数组处理数据
foreach (var item in structArray)
{
    // 示例输出逻辑,可根据需求修改
    Console.WriteLine($"Active: {item.Active}, Value: {item.Value}");
}

// 字节转结构体数组的核心函数
private static STRUCT_A[] ConvertBytesToStructArray(byte[] bytes)
{
    int structSize = Marshal.SizeOf(typeof(STRUCT_A));
    int arrayLength = bytes.Length / structSize;
    STRUCT_A[] result = new STRUCT_A[arrayLength];

    GCHandle pinnedHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
    try
    {
        IntPtr basePtr = pinnedHandle.AddrOfPinnedObject();
        for (int i = 0; i < arrayLength; i++)
        {
            result[i] = Marshal.PtrToStructure<STRUCT_A>(basePtr + i * structSize);
        }
    }
    finally
    {
        pinnedHandle.Free();
    }

    return result;
}

方式二:手动解析字节(灵活适配不同字节序/对齐规则)

如果PLC的内存对齐或字节序和本地环境不一致,手动解析更可控:

// 读取字节数组的代码同上
byte[] rawBytes = plc.Read(MyTags);
STRUCT_A[] structArray = ConvertBytesToStructArrayManual(rawBytes);

// 手动转换函数
private static STRUCT_A[] ConvertBytesToStructArrayManual(byte[] bytes)
{
    // 单个STRUCT_A的字节大小,需根据PLC实际存储规则调整(示例为1字节bool + 4字节int = 5字节)
    int structByteSize = 5;
    int arrayLength = bytes.Length / structByteSize;
    STRUCT_A[] result = new STRUCT_A[arrayLength];

    for (int i = 0; i < arrayLength; i++)
    {
        int offset = i * structByteSize;
        // 解析bool:PLC中通常非0值表示true
        result[i].Active = bytes[offset] != 0;
        // 解析int:默认适配小端字节序,若PLC为大端需反转字节
        result[i].Value = BitConverter.ToInt32(bytes, offset + 1);
        
        // 大端字节序处理示例:
        // byte[] intBytes = new byte[4];
        // Array.Copy(bytes, offset + 1, intBytes, 0, 4);
        // Array.Reverse(intBytes);
        // result[i].Value = BitConverter.ToInt32(intBytes, 0);
    }

    return result;
}

关键注意事项

  • 结构体的Pack参数必须和PLC的内存对齐规则一致,若PLC采用4字节对齐,需将Pack设为4,此时结构体总大小会变为8字节(bool占1字节,填充3字节后存储int)。
  • 确认PLC的字节序(大端/小端),手动解析时对应调整字节顺序。
  • 确保读取的字节数组长度是单个结构体字节数的整数倍,避免数据截断。

内容的提问来源于stack exchange,提问作者cszynkowski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 20:55:13