2014-01-07 2 views
4

я в настоящее время участвует в проекте в порт C++ в C# код, но некоторые фрагменты не так легко портировать 1 до 1, как следующее:Преобразовать C++ код (с указателями и битового сдвига) на C#

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

Я знаю, что это может быть понято как ленивый вопрос, но я подумал, что, возможно, это поможет мне в этом.

Благодаря

+0

Предполагая, что скорость и т. Д. Являются величинами с плавающей точкой, я полагаю, что строки 'Speed ​​* 10' должны сохранять одну десятичную цифру. значение «CMND_MOVEL», равное 10, может указывать на это ... или это может быть что-то другое. – melak47

ответ

2

Исходный код, вероятно, предполагает, что sizeof(int) - это 4, что не гарантируется стандартом. Во всяком случае, он использует первый байт для хранения бит CMND_MOVEL и CMD_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 | 
------------------------------------------------------------- 

Каждый char в C/C++ является один байт, соответствующий byte типа в C#. Автор хочет отправить значения, которые длиннее этого, поэтому они используют 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

Я постараюсь добавить некоторые комментарии для осветления

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

Lukas уже охвачены большинство из них; но то, что он эффективно делает, перемещается по массиву с помощью математики указателя. Так что это:

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

в C# будет выглядеть следующим образом

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

и так далее.

Смежные вопросы