سؤال

لدي وظيفة تقوم بإنشاء بايت فحص CRC بناءً على محتوى أي حزمة. تكمن المشكلة في ترجمة الوظيفة من C++ إلى 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*(packet) على أنها LPBYTE، والفكرة هي أن القيمة المخصصة لـ *packet يتم تعيينها إلى *ptr وكما ترى *ptr يزيد. وهذا يعني أنه يتم تمرير مصفوفة بايت وزيادة قيمة المؤشر يذهب إلى البايت التالي.

لقد حاولت القيام بذلك باستخدام لغة 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;
    }

لا يبدو الأمر بهذا السوء، لكن لا يمكنني تسميته

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

خطأ:"يمكنك فقط أخذ عنوان التعبير غير الثابت داخل مُهيئ بيان ثابت"

يرجى الملاحظة

packetbuffer في كل من تطبيقات C++ وC# هو byte[] packetBuffer = new byte[18];

هل كانت مفيدة؟

المحلول

هل يمكن أن تجعل طريقة يقبل صفيف بايت:

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

ومن الأفضل للحفاظ على الاشياء غير آمنة مخبأة بعيدا قدر المستطاع واجهات المدار خلف.

وبعد ذلك اصفا اياه بانه سيكون من السهل:

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

في الواقع، سيكون من الأفضل أن تكتب GenerateCheckByte للعمل على مجموعة على أي حال، بدلا من الخوض في تقنيات 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;
}

واكتب أبسط، أسلم تنفيذ ما تستطيع، والفوضى الوحيد مع مؤشرات إذا وجدت اختناق في التنميط.

هل مجرد ترجمة الكثير من C الموجودة / C ++ إلى C #؟ هناك نقطة صغيرة يفعل ذلك إلا إذا كنت الحصول على بعض السلامة الجديدة / الصيانة منه. :)

نصائح أخرى

ويجب أن لا يكون لاستخدام رمز غير آمنة على الإطلاق. إذا قمت بإرسال في صفيف بايت إلى وظيفة، فإنه يمكن الوصول إليها دون استخدام المؤشرات.

وأنا لم تختبر رمز، لكن يجب أن يكون شيء من هذا القبيل:

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

تحتاج إلى "تثبيت" مصفوفة البايت في الذاكرة لاستخدامها كبايت*.

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

مراجع:

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top