将C ++代码(带指针和位移)转换为C#

时间:2014-01-07 16:07:03

标签: c# c++ pointers

我目前正参与一个将C ++移植到C#代码的项目,但是有些片段并不容易移植到1到1,如下所示:

#define CMND_MOVEL              10
#define CMND_EXTRASIDE          0x80

char CmndBuffer[32];

int *dst;
dst = (int*) &CmndBuffer[0];

*dst = 0;
*dst |= (CMND_MOVEL + (Flags << 8));      
if (BoxSide) *dst |= CMND_EXTRASIDE;

dst++;
*dst = SequenceNr;
dst++;
*dst = 10 * LastDestination.x;
dst++;
*dst = 10 * LastDestination.y;
dst++;
*dst = 10 * LastDestination.z;
dst++;
*dst = Speed * 10;
dst++;
*dst = Accel * 10;    

result = ERR_COMMSOCK;
if (UdpCmdSocket >= 0)
{
    if (sendto(UdpCmdSocket, (const char*) CmndBuffer, 28, 0, (struct sockaddr*)&UdpCmdPeer, sizeof(UdpCmdPeer)) != SOCKET_ERROR)
    {
        // more logic here
    }
}

有人可以详细解释我这里发生了什么吗?我非常清楚指针和位移如何工作,但我不是100%肯定在字节级上发生了什么。我看到的是它正在填充数据包以将其丢弃到UDP上。

但更重要的是:我如何用C#发送? (我将使用.NET Socket类)

我知道它可以被认为是一个懒惰的问题,但我想也许可以帮助我解决这个问题。

由于

3 个答案:

答案 0 :(得分:2)

我会尝试添加一些注释以澄清

//some constants for later use
#define CMND_MOVEL              10
#define CMND_EXTRASIDE          0x80

char CmndBuffer[32];

int *dst;
//Load the address of the first element of CmndBuffer into dst;
dst = (int*) &CmndBuffer[0];

//CmndBuffer[0] to zero
*dst = 0;
//this loads (CMND_MOVEL + (Flags << 8) into dst. Flags << 8 means a multiplication with 2^8
*dst |= (CMND_MOVEL + (Flags << 8));      
if (BoxSide) *dst |= CMND_EXTRASIDE;

//go to the next array element. The same applies to the commands below
dst++;
//write the value into the current array element
*dst = SequenceNr;
dst++;
*dst = 10 * LastDestination.x;
dst++;
*dst = 10 * LastDestination.y;
dst++;
*dst = 10 * LastDestination.z;
dst++;
*dst = Speed * 10;
dst++;
*dst = Accel * 10;    

result = ERR_COMMSOCK;
if (UdpCmdSocket >= 0)
{
    if (sendto(UdpCmdSocket, (const char*) CmndBuffer, 28, 0, (struct sockaddr*)&UdpCmdPeer, sizeof(UdpCmdPeer)) != SOCKET_ERROR)
    {
        // more logic here
    }
}

关于问题的第二部分,请查看this

答案 1 :(得分:2)

原始代码可能假设sizeof(int)为4,标准无法保证。无论如何,它使用第一个字节来保存CMND_MOVELCMD_EXTRASIDE位,剩下的3个字节保存Flags的值。布局是这样的:

-------------------------------------------------------------
| Flags<<8      | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| CMD_MOVEL     | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 |
| CMD_EXTRASIDE | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
-------------------------------------------------------------

C / C ++中的每个char都是一个字节,对应于C#中的byte类型。作者希望发送长于此值的值,因此他们使用int*一次写入4个字节。

这部分:

//CmndBuffer[0] to zero
*dst = 0;

实际设置为0 CmndBuffer[0]CmdBuffer[3]。由于他们将dst指针递增六次,因此最终会写入CmdBuffer[27]。最后四个字节似乎留有未初始化的值。

如果要逐字节写入,则需要使用位移和屏蔽。类似的东西:

byte[] buffer = /*...*/;
int index = /*...*/;
int sequenceNr = /*...*/;

buffer[index] = (byte) (sequenceNr >> 24) & 0xFF;
buffer[++index] = (byte) (sequenceNr >> 16) & 0xFF;
buffer[++index] = (byte) (sequenceNr >> 8) & 0xFF;
buffer[++index] = (byte) sequenceNr & 0xFF;

答案 2 :(得分:1)

卢卡斯已经涵盖了大部分内容;但它实际上正在做的是使用指针数学移动数组。所以这个:

    dst++;
    *dst = 10 * LastDestination.x;
C#中的

看起来像这样

    var arrayIndex = 0;
    CmndBuffer[arrayIndex++] = 10 * LastDestination.x;
    CmndBuffer[arrayIndex++] = 10 * LastDestination.y;

等等。