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.