Wie zuweisen byte [] als Zeiger in C #
Frage
Ich habe eine Funktion, die einen CRC-Prüfungs-Byte basierend auf dem Inhalt eines Paket Problem erzeugt, ist die Funktion von C ++ zu C # in übersetzen
C ++ Code:
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;
}
das char * (Paket) können auch als LPBYTE definiert werden, ist die Idee, dass der Wert Paket an * zugeordnet ist * ptr zugewiesen und wie Sie sehen * zgr increases.Meaning ein Byte-Array wird übergeben und durch die zunehmende Wert des Zeigers geht es auf das nächste Byte.
Ich habe versucht, es in C # zu tun, und es versäumt, viele times.After einige harte Arbeit, die ich einige Code herausgefunden, aber ich kann es nicht ausführen:
C # -Code
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;
}
Es sieht nicht so schlecht, aber ich kann es nicht nennen
unsafe
{
packetBuffer[5] = Functions.GenerateCheckByte(&packetBuffer[0], 18, packet.seedCRC);
}
Fehler: „Sie können nur die Adresse eines nicht fixierten Ausdruck nehmen innerhalb einer festen Aussage initializer“
Bitte beachten
packetbuffer sowohl in C ++ und C # Anwendung ist byte [] packetBuffer = new byte [18];
Lösung
Sie könnte das Verfahren ein Byte-Array machen akzeptieren:
public static unsafe byte GenerateCheckByte(byte[] packetArray, int length, UInt32 seed)
{
fixed(byte *packet = packetArray)
{
... etc
}
}
Es ist besser, die unsicheren Sachen wie möglich hinter verwalteten Schnittstellen so viel versteckt zu halten.
Dann ruft es wäre einfach:
packetBuffer[5] = Functions.GenerateCheckByte(packetBuffer, 18, ...
In der Tat wäre es besser, GenerateCheckByte
zu schreiben ohnehin auf einem Array zu betreiben, statt Eintauchen in unsafe
Techniken:
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;
}
Schreiben Sie die einfachste, sicherste Implementierung Sie können, und nur Chaos mit Zeigern, wenn Sie einen Engpass in Profilierung finden.
Übersetzen Sie nur eine Menge vorhandenen C / C ++ in C #? Es macht wenig Sinn, das zu tun, wenn Sie einige neue Sicherheits / Wartbarkeit von ihm erhalten. :)
Andere Tipps
Sie sollten nicht zu einer unsicheren Code überhaupt zu verwenden. Wenn Sie in einem Byte-Array an die Funktion senden, können sie darauf zugreifen, ohne Zeiger verwendet wird.
Ich habe den Code nicht getestet, aber es sollte wie folgt sein:
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)
);
}
Sie müssen ‚pin‘ der Byte-Array in dem Speicher als ein Byte * zu verwenden.
byte checksum;
fixed(byte* pPacketBuffer = packetBuffer)
{
checksum = Functions.GenerateCheckByte(pPacketBuffer, 18, packet.seedCRC)
}
packetBuffer[5] = checksum
Referenzen: