Comment attribuer octet [] comme un pointeur en C #
Question
I ai une fonction qui génère un octet de contrôle CRC sur la base du contenu d'un paquet problème est de traduire la fonction de C ++ à C #
Le code C de:
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;
}
le paquet char * (paquet) peut également être défini comme LPBYTE, l'idée est que la valeur attribuée à * est attribué à * ptr et que vous voyez * ptr increases.Meaning un tableau d'octets est passé et en augmentant la valeur du pointeur, il va à l'octet suivant.
J'ai essayé de le faire en C # et beaucoup fois.Après échouais un travail acharné que j'ai compris un peu de code, mais je ne peux pas l'exécuter:
code C #
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;
}
Il ne semble pas si mal que ça, mais je ne peux pas l'appeler
unsafe
{
packetBuffer[5] = Functions.GenerateCheckByte(&packetBuffer[0], 18, packet.seedCRC);
}
erreur: « Vous ne pouvez prendre l'adresse d'une expression non fixée à l'intérieur d'une déclaration fixe initialiseur »
S'il vous plaît noter
packetbuffer dans les deux C ++ et C # application est byte [] packetBuffer = new byte [18];
La solution
Vous pouvez faire la méthode accepter un tableau d'octets:
public static unsafe byte GenerateCheckByte(byte[] packetArray, int length, UInt32 seed)
{
fixed(byte *packet = packetArray)
{
... etc
}
}
Il est préférable de garder les choses dangereuses caché autant que possible par des interfaces gérées.
Alors appelle, il serait facile:
packetBuffer[5] = Functions.GenerateCheckByte(packetBuffer, 18, ...
En fait, il serait préférable d'écrire GenerateCheckByte
pour fonctionner sur un tableau de toute façon, au lieu de plonger dans les techniques 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;
}
Ecrire la plus simple, la plus sûre mise en œuvre, vous pouvez, et ne plaisante pas avec des pointeurs si vous trouvez un goulot d'étranglement dans le profilage.
Êtes-vous juste traduisez beaucoup d'exister C / C ++ en C #? Il y a peu d'intérêt à faire que si vous obtenez une nouvelle sécurité / maintenabilité de celui-ci. :)
Autres conseils
Vous ne devriez pas avoir à utiliser le code dangereux du tout. Si vous envoyez dans un tableau d'octets à la fonction, il peut y accéder sans utiliser des pointeurs.
Je ne l'ai pas testé le code, mais il devrait être quelque chose comme ceci:
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)
);
}
Vous devez « pin » du tableau d'octets en mémoire pour l'utiliser comme un octet *.
byte checksum;
fixed(byte* pPacketBuffer = packetBuffer)
{
checksum = Functions.GenerateCheckByte(pPacketBuffer, 18, packet.seedCRC)
}
packetBuffer[5] = checksum
Références: