简体   繁体   中英

Convert C++ code (with pointers and bit shifting) to C#

I'm currently involved in a project to port C++ to C# code but some fragments are not that easy to port 1 to 1, like the following:

#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
    }
}

Can someone explain me in detail what is happening here? I know fairly well how pointers and bit shifting works but i'm not 100% sure whats happening here on byte level. What I see is that it is populating a data packet to throw it over UDP.

But far more important: how do I send this in C#?? (I will use the .NET Socket class)

I know it can be conceived as a lazy question but I thought maybe SO can help me with this.

Thanks

I will try to add some comments for clarification

//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
    }
}

as for the second part of your question have a look at this

The original code is probably assuming sizeof(int) is 4, which is not assured by the standard. At any rate, it is using the first byte to hold the CMND_MOVEL and CMD_EXTRASIDE bits and the remaining 3 bytes to hold the value of Flags . The layout is like this:

-------------------------------------------------------------
| 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 |
-------------------------------------------------------------

Each char in C/C++ is a single byte, corresponding to the byte type in C#. The author wants to send values which are longer than this, so they are using an int* to write 4 bytes at a time.

This part:

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

Actually sets to 0 CmndBuffer[0] through CmdBuffer[3] . Since they increment the dst pointer six times, they end up writing up to CmdBuffer[27] . The last four bytes seem to be left with uninitialized values.

If you wanted to write it byte-by-byte, you would need to use bit-shifting and masking. Something like:

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;

Lukas already covered most of it; but what it is effectively doing is moving along an array using pointer math. So this:

    dst++;
    *dst = 10 * LastDestination.x;

in C# would look like this

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

and so on.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM