首页 > 解决方案 > 从 C++ 转换的 C# 代码不起作用

问题描述

考虑以下通过 RS232 向设备发送数据的 C++ 代码。

  strcpy(m_MsgBytes, "SRT1");

  iTmp = finalizeNL20Message(m_MsgBytes, 4);

int CVTSSLTNL20Message::finalizeNL20Message(BYTE *pMsgData, int iInLen)
{
  BYTE ucMsg[MAX_MESSAGE_LENGTH];

  ucMsg[0]  = MSG_STX; // 0x02
  ucMsg[1]  = NL20_BLOCK_ID; // ox01
  ucMsg[2]  = ATTR_CMD; // 'C'

  memcpy(&ucMsg[3], pMsgData, iInLen);

  ucMsg[3 + iInLen] = MSG_ETX;
  ucMsg[4 + iInLen] = calculateNL20Checksum(ucMsg, 4 + iInLen);
  ucMsg[5 + iInLen] = MSG_CR;
  ucMsg[6 + iInLen] = MSG_LF;

  memcpy(pMsgData, ucMsg, 7 + iInLen);

  return 7 + iInLen;
}

BYTE CVTSSLTNL20Message::calculateNL20Checksum(const BYTE *pData, int iInLen)
{
  BYTE ucChk = 0;

  for (int iCnt = 0; iCnt < iInLen; iCnt++)
    ucChk = ucChk ^ pData[iCnt];

 return ucChk;

}

我用 C# 重写了这段代码,如下所示:

public static string Generate()
{
    return RIONNLHelper.FinalizeMessage("SRT1");
}

public static string FinalizeMessage(string data)
{
    //STX=0x02 NL20BLOCKID=0x01 Command=C (Command from computer)
    data = "\x02\x01C" + data;

    //ETX=0x03 
    data += "\x03";
    data += (char)calculateNL20CheckSum(data);
    data += "\r\n";

    return data;
}

public static byte calculateNL20CheckSum(string data)
{
    byte chk = 0;

    foreach (byte b in Encoding.ASCII.GetBytes(data))
    {
        chk ^= b;
    }

    return chk;
}

并且在发送之前将字符串转换为字节数组

bytes = data.Select(c=>(byte)c).ToArray(); 现在的问题是,C# 代码永远不会从设备获得对这些请求的响应。它确实将其他数据发送回来,波特率如此之高,一切都是正确的。

我对从 C++ 代码翻译缓冲区有一些疑问。0x020x01C 数据 0x03 校验和 \r\n

变成了

\x02\x01C 数据 \x03 校验和 \r\n

否则校验和计算的重写是否正确?首先计算字节的校验和,然后转换回 char

标签: c#c++

解决方案


这是一个奇怪的。与往常一样,我创建了一个单元测试。然后我使用 C++ CLR 构建了 C++ 版本,并进行了测试以将输出与您的输入“SRT1”进行比较。最初,它失败了

C++ version:  02 01 43 53 52 54 31 03 27 0d 0a 
C# version:   02 1c 53 52 54 31 03 79 0d 0a

那个1C看着挺眼熟的……

错误似乎在于字符串"\x02\x01C" + data; 与十六进制转义相同"\x02" + "\x01" + "C" + data;,将继续解释数字,直到找到不是十六进制数字的字符。所以“C”成为十六进制转义的一部分。

分解文字允许解析器将“C”解析为单独的字符,然后单元测试通过。


推荐阅读