Cómo asignar byte [] como un puntero en C #
Pregunta
Tengo una función que genera un byte de comprobación CRC basado en el contenido de cualquier packet.The problema es en la traducción de la función de C ++ a C #
código C ++:
unsigned char GenerateCheckByte( char* packet, int length, unsigned long seed )
{
if( !packet ) return 0;
unsigned long checksum = 0xFFFFFFFF;
length &= 0x7FFF;
char* ptr = packet;
unsigned long moddedseed = seed << 8;
for( int i = 0; i < length; i++ )
checksum = ( checksum >> 8 ) ^ table[moddedseed + ( ( *(ptr++) ^ checksum ) & 0xFF )];
unsigned char result = ( (checksum>>24)&0xFF ) + ( (checksum>>8)&0xFF ) + ( (checksum>>16)&0xFF ) + ( checksum&0xFF );
return result;
}
char * (paquete) también se puede definir como LPBYTE, la idea es que el valor asignado a * paquete se asigna a * ptr y como ves * PTR increases.Meaning una matriz de bytes se pasa en y por el aumento de la valor del puntero se pasa al siguiente byte.
He intentado hacerlo en C # y fracasado muchas times.After un duro trabajo me di cuenta de algo de código, pero no puedo ejecutarlo:?
C # código
public static unsafe byte GenerateCheckByte(byte *packet, int length, UInt32 seed )
{
if (*packet == 0)
return 0;
UInt32 checksum = 0xFFFFFFFF;
length &= 0x7FFF;
byte *ptr = packet;
UInt32 moddedseed = seed << 8;
for (int i = 0; i < length; i++)
checksum = ( checksum >> 8 ) ^ Table.table[moddedseed + ( ( *(ptr++) ^ checksum ) & 0xFF )];
byte result = (byte)(( (checksum>>24)&0xFF ) + ( (checksum>>8)&0xFF ) + ( (checksum>>16)&0xFF ) + ( checksum&0xFF ));
return result;
}
No se ve tan mal, pero no puedo llamarlo
unsafe
{
packetBuffer[5] = Functions.GenerateCheckByte(&packetBuffer[0], 18, packet.seedCRC);
}
error: "Sólo se puede tomar la dirección de una expresión no fijado dentro de un inicializador de la sentencia fija"
Atención:
packetbuffer tanto en ++ y aplicación # C C es byte [] packetBuffer = byte nuevo [18];
Solución
Se podría hacer que el método acepta una matriz de bytes:
public static unsafe byte GenerateCheckByte(byte[] packetArray, int length, UInt32 seed)
{
fixed(byte *packet = packetArray)
{
... etc
}
}
Es mejor mantener las cosas inseguras escondido en lo posible las interfaces detrás gestionados.
A continuación, llamando sería fácil:
packetBuffer[5] = Functions.GenerateCheckByte(packetBuffer, 18, ...
De hecho, sería mejor escribir GenerateCheckByte
para funcionar en una gran variedad de todos modos, en lugar de profundizar en las técnicas de unsafe
:
public static unsafe byte GenerateCheckByte(byte[] packet, int length, UInt32 seed )
{
if (packet == null)
throw new ArgumentNullException("packet"); // the right way in C#
UInt32 checksum = 0xFFFFFFFF;
length &= 0x7FFF;
UInt32 moddedseed = seed << 8;
for (int i = 0; i < length; i++)
checksum = ( checksum >> 8 ) ^ Table.table[moddedseed + ( ( packet[i] ^ checksum ) & 0xFF )];
byte result = (byte)(( (checksum>>24)&0xFF ) + ( (checksum>>8)&0xFF ) + ( (checksum>>16)&0xFF ) + ( checksum&0xFF ));
return result;
}
Escribir el más simple, más segura aplicación se puede, y sólo meterse con punteros si encuentra un cuello de botella en perfiles.
¿Usted apenas está traduciendo un montón de C existente / C ++ en C #? No tiene mucho sentido hacer eso a menos que obtenga una nueva seguridad / capacidad de mantenimiento de la misma. :)
Otros consejos
Usted no debería tener que usar código no seguro en absoluto. Si envía una matriz de bytes a la función, se puede acceder a él sin el uso de punteros.
No he probado el código, pero debería ser algo como esto:
byte GenerateCheckByte(byte[] packet, ulong seed) {
if (packet == null) return 0;
int length = packet.Length & 0x7FFF;
ulong checksum = 0xFFFFFFFF;
ulong moddedseed = seed << 8;
for (int i = 0; i < length; i++) {
checksum = (checksum >> 8) ^ table[moddedseed + ((packet[i] ^ checksum) & 0xFF)];
}
return (byte)(
((checksum >> 24) & 0xFF) +
((checksum >> 16) & 0xFF) +
((checksum >> 8) & 0xFF) +
(checksum & 0xFF)
);
}
Es necesario 'pin' la matriz de bytes en la memoria para utilizarlo como un byte *.
byte checksum;
fixed(byte* pPacketBuffer = packetBuffer)
{
checksum = Functions.GenerateCheckByte(pPacketBuffer, 18, packet.seedCRC)
}
packetBuffer[5] = checksum
Referencias: