我有一个函数可以根据任何数据包的内容生成CRC校验字节。问题在于将函数从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];答案 0 :(得分:5)
你可以让方法接受一个字节数组:
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#?除非你从中获得一些新的安全性/可维护性,否则没有什么意义。 :)
答案 1 :(得分:2)
您根本不必使用不安全的代码。如果向函数发送一个字节数组,它可以在不使用指针的情况下访问它。
我没有测试过代码,但它应该是这样的:
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)
);
}
答案 2 :(得分:1)
您需要将字节数组“固定”到内存中,以将其用作字节*。
byte checksum;
fixed(byte* pPacketBuffer = packetBuffer)
{
checksum = Functions.GenerateCheckByte(pPacketBuffer, 18, packet.seedCRC)
}
packetBuffer[5] = checksum
参考文献: