using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace ZLGUSBCANFD { public class _Msg_ { public int msg_type { get; set; } public int msg_id { get; set; } public int msg_cyclic { get; set; } public byte msg_dlc { get; set; } public string msg_name { get; set; } public string[] signal_Name { get; set; } public int msg_brs { get; set; } } public enum Msg_Type { CAN = 0, CANFD = 1, } public class ZLGDBCParser { // 补齐这个属性!4个通道的静态报文数据库缓存,供 ViewModel 直接读取 public static List> MsgDatabase { get; set; } = [.. Enumerable.Range(0, 4).Select(_ => new List<_Msg_>())]; /// /// 外部调用:解析特定通道的 DBC 并自动存入对应的 MsgDatabase 缓存中 /// /// ZDBC句柄 /// 通道号索引 (0-11) public static void ParseAndLoadToDatabase(uint chDbcHandle, int channel) { if (channel < 0 || channel >= MsgDatabase.Count) return; // 清空当前通道旧缓存 MsgDatabase[channel].Clear(); // 解析并填充 var parsedList = ParseZlgDbc(chDbcHandle); MsgDatabase[channel].AddRange(parsedList); } /// /// 全手工解析周立功 DBC 句柄下的所有消息和信号 /// /// 对应通道的 ZDBC 句柄 /// 返回对齐同星业务层的自定义报文列表 public static List<_Msg_> ParseZlgDbc(uint chDbcHandle) { List<_Msg_> msgList = new List<_Msg_>(); // 显式指定周立功命名空间下的 INVALID_DBC_HANDLE 校验 if (chDbcHandle == 0 || chDbcHandle == ZLGUSBCANFD.ZDBC.INVALID_DBC_HANDLE) return msgList; // 显式指定周立功命名空间下的结构体大小 int msgSize = Marshal.SizeOf(typeof(ZLGUSBCANFD.ZDBC.DBCMessage)); IntPtr pMsg = Marshal.AllocHGlobal(msgSize); try { // 1. 获取周立功 DBC 的第一条报文 bool hasMessage = ZLGUSBCANFD.ZDBC.ZDBC_GetFirstMessage(chDbcHandle, pMsg); while (hasMessage) { // 强制指定周立功底层 DBCMessage 结构映射 var zlgMsg = (ZLGUSBCANFD.ZDBC.DBCMessage)Marshal.PtrToStructure(pMsg, typeof(ZLGUSBCANFD.ZDBC.DBCMessage)); // 1. 优先在字节数组中找到第一个 \0 的位置 int nullIndex = Array.IndexOf(zlgMsg.strName, (byte)0); _Msg_ myMsg = new _Msg_ { msg_id = (int)zlgMsg.nID, // 2. 只翻译 \0 之前的有效字节,彻底解决乱码与规避不必要的内存开销 msg_name = nullIndex >= 0 ? Encoding.Default.GetString(zlgMsg.strName, 0, nullIndex) : Encoding.Default.GetString(zlgMsg.strName).TrimEnd('\0'), msg_dlc = (byte)zlgMsg.nSize, msg_cyclic = (int)zlgMsg.nCycleTime, // 如果底层识别出是扩展帧(nExtend==1),这里对齐映射为你的业务类型 msg_type = zlgMsg.nExtend == 1 ? (int)Msg_Type.CANFD : (int)Msg_Type.CAN, signal_Name = new string[zlgMsg.nSignalCount] }; // 2. 提取该报文下的所有信号名称 for (int i = 0; i < zlgMsg.nSignalCount; i++) { var signal = zlgMsg.vSignals[i]; string sigName = Encoding.Default.GetString(signal.strName).TrimEnd('\0'); myMsg.signal_Name[i] = sigName; } msgList.Add(myMsg); // 3. 移向下一条报文 hasMessage = ZLGUSBCANFD.ZDBC.ZDBC_GetNextMessage(chDbcHandle, pMsg); } } finally { // 彻底释放非托管内存,避免上位机高频切换加载 DBC 时导致内存泄漏 Marshal.FreeHGlobal(pMsg); } // 按 ID 排序,对齐你的树状展现或者二分查找业务逻辑 msgList.Sort((a, b) => a.msg_id.CompareTo(b.msg_id)); return msgList; } } }