Domanda

Ho una funzione che genera un controllo CRC byte in base al contenuto di ogni pacchetto.Il problema è tradurre la funzione da C++ a C#

Il codice 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*(pacchetto) può essere definita anche come LPBYTE,l'idea è che il valore assegnato a *pacchetto viene assegnato a *ptr e, come vedi, *ptr aumenta.Significato di una matrice di byte è passato e aumentando il valore del puntatore va al byte successivo.

Ho provato a farlo in C# e fallito molte volte.Dopo il duro lavoro che ho capito un po ' di codice,ma non riesco a eseguirlo :?

Codice 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;
    }

Non sembra male,ma io non riesco a chiamare

  unsafe
  {
      packetBuffer[5] = Functions.GenerateCheckByte(&packetBuffer[0], 18, packet.seedCRC);
  }

errore:"Si può prendere solo l'indirizzo di un slegati espressione all'interno di un fisso istruzione di inizializzazione"

Si prega di notare

packetbuffer sia in C++ e C# richiesta byte[] packetBuffer = new byte[18];

È stato utile?

Soluzione

Si potrebbe rendere il metodo accetta un array di byte:

public static unsafe byte GenerateCheckByte(byte[] packetArray, int length, UInt32 seed)
{
    fixed(byte *packet = packetArray)
    {
        ... etc
    }
}

Meglio stare sicuri roba nascosto quanto più possibile dietro gestito interfacce.

Chiamando quindi sarebbe facile:

packetBuffer[5] = Functions.GenerateCheckByte(packetBuffer, 18, ...

In effetti, sarebbe meglio scrivere GenerateCheckByte per operare su un array comunque, invece di approfondire unsafe tecniche:

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;
}

Scrivere il più semplice, più sicuro di attuazione è possibile, e solo pasticciare con i puntatori se si trova un collo di bottiglia nella profilatura.

Sono appena traducendo un sacco di C/C++ esistente in C#?C'è un piccolo punto a fare che a meno che non si ottiene alcuni nuovi dispositivi di sicurezza/manutenzione da esso.:)

Altri suggerimenti

Non si deve utilizzare il codice unsafe a tutti.Se si invia in una matrice di byte per la funzione, è possibile accedervi senza l'utilizzo di puntatori.

Non ho testato il codice, ma dovrebbe essere qualcosa di simile a questo:

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)
    );
}

Hai bisogno di 'pin' la matrice di byte in memoria di usarlo come un byte*.

byte checksum; 
fixed(byte* pPacketBuffer = packetBuffer)
{
    checksum = Functions.GenerateCheckByte(pPacketBuffer, 18, packet.seedCRC) 
}
packetBuffer[5] = checksum 

Riferimenti:

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top