代码之家  ›  专栏  ›  技术社区  ›  Serve Laurijssen

C代码转换为C++不工作

  •  0
  • Serve Laurijssen  · 技术社区  · 8 年前

    考虑下面的C++代码,它通过RS232发送数据到一个设备。

      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 data\x03校验和\r\n

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

    2 回复  |  直到 8 年前
        1
  •  2
  •   Pete Kirkham    8 年前

    这是一个奇怪的。一如既往,我创建了一个单元测试。然后用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”解析为单独的字符,然后单元测试通过。

        2
  •  1
  •   xanatos    8 年前

    MMH…您的问题可能是某些代码使用 Encoding.ASCII.GetBytes(finalString) 最终转换 string byte[] ,但校验和可以是>=0x7f,所以是非ascii字符。转换 一串 字节[] 之后手动 Generate 像:

    string result = Generate();
    byte[] bytes = new byte[result.Length];
    for (int i = 0; i < result.Length; i++)
    {
        bytes[i] = (byte)result[i];
    }
    

    为了确保改变:

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

    foreach (char ch in data)
    {
        chk ^= (byte)ch;
    

    或者你可以使用 Encoding.GetEncoding("iso-8859-1") 映射值的 0x00-0xFF 到Unicode值 0x0000-0x00FF .

    作为 Pete Kirkham 注意,除非你有 data 带字符> 0x7F ,校验和将为<0x7f。这是因为 ^ 运算符将只返回带有(1^0)或(0^1)的1,因此您必须在1的某个位置有8位,才能有8位为1的校验和。