문제

모든 패킷의 내용을 기반으로 CRC Check Byte를 생성하는 함수가 있습니다. 문제는 C ++에서 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 *(패킷)는 lpbyte로 정의 될 수 있습니다. 아이디어는 *패킷에 할당 된 값이 *ptr에 할당되고 *ptr이 증가하는대로, 바이트 배열이 전달되고 포인터 다음 바이트로갑니다.

나는 C#에서 그것을하려고 노력했고 여러 번 실패했습니다. 어려운 일 후에는 코드를 알아 냈지만 실행할 수는 없습니다.?

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

오류 : "고정 된 명령문 초기화 내에서 고정되지 않은 표현식의 주소 만 가져갈 수 있습니다."

참고하십시오

C ++ 및 C# 응용 프로그램의 PacketBuffer는 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