Python выполняет побайтовые операции на коротких, а не на инт. - PullRequest
1 голос
/ 21 января 2020

Как мне написать следующую C программу на Python? Проблема заключается в том, что Python считает crc int, а не short, и, следовательно, результатом является полная ерунда ...

unsigned short special_crc16(volatile unsigned char *sbuf,unsigned int len){
    unsigned short crc=0xFFFF;

    while(len){
        crc=(unsigned char)(crc >> 8) | (crc << 8);
        crc^=(unsigned char) *sbuf;
        crc^=(unsigned char)(crc & 0xff) >> 4;
        crc^=(crc << 8) << 4;
        crc^=((crc & 0xff) << 4) << 1;
        len--;
        sbuf++;
    }
    return crc;
}

Ввод: 8C 4C Ожидаемый результат: CA B2

Моя Python 3 попытка:

def compute(data, datalen):
    crc=0xFFFF
    for i in range(0, datalen):
        crc = (crc >> 8) | (crc << 8)
        crc = crc ^ data[i]
        crc = crc ^ ((crc & 0xff) >> 4)
        crc = crc ^ ((crc << 8) << 4)
        crc = crc ^ (((crc & 0xff) << 4)<<1)

    return crc

возвращает FFFF00F030C2B2 ...

Спасибо!

Ответы [ 2 ]

1 голос
/ 21 января 2020

Я нашел решение: работай с int, но сделай 0x0000FFFF, чтобы рассмотреть только первые 2 байта и симулировать короткий.

Что-нибудь лучше?

def compute(data, datalen):
    crc=0x0000FFFF
    for i in range(0, datalen):
        crc = ((crc >> 8) & 0x0000ffff) | ((crc << 8) & 0x0000ffff)
        crc = crc ^ data[i]
        crc = crc ^ (((crc & 0xff) >> 4) & 0x0000ffff)
        crc = crc ^ ((crc << 12) & 0x0000ffff)
        crc = crc ^ (((crc & 0xff) << 5) & 0x0000ffff)

    return crc
0 голосов
/ 21 января 2020

Вы всегда можете бросить свой собственный класс для 16-битного Int. Очевидно, что не все эти методы должны быть написаны для вашего случая, и я также опустил несколько.

class UShort:
    def __init__(self, x):
        self._x = int(x) & 0xffff

    def __repr__(self):
        return '<UShort {}>'.format(self._x)

    @classmethod
    def to_short(cls, x):
        return cls(int(x) & 0xffff)

    @property
    def hex(self):
        return hex(self._x)

    def __add__(self, other): return self.to_short(self._x + self.to_short(other)._x)
    def __sub__(self, other): return self.to_short(self._x - self.to_short(other)._x)
    def __mul__(self, other): return self.to_short(self._x * self.to_short(other)._x)
    def __div__(self, other): return self.to_short(self._x / self.to_short(other)._x)
    def __mod__(self, other): return self.to_short(self._x % self.to_short(other)._x)
    def __pow__(self, other): return self.to_short(self._x ** self.to_short(other)._x)
    def __and__(self, other): return self.to_short(self._x & self.to_short(other)._x)
    def __xor__(self, other): return self.to_short(self._x ^ self.to_short(other)._x)
    def __or__(self, other): return self.to_short(self._x | self.to_short(other)._x)
    def __lshift__(self, other): return self.to_short(self._x << self.to_short(other)._x)
    def __rshift__(self, other): return self.to_short(self._x >> self.to_short(other)._x)
    def __radd__(self, other): return self.to_short(self.to_short(other)._x + self._x)
    def __rsub__(self, other): return self.to_short(self.to_short(other)._x - self._x)
    def __rmul__(self, other): return self.to_short(self.to_short(other)._x * self._x)
    def __rdiv__(self, other): return self.to_short(self.to_short(other)._x / self._x)
    def __rmod__(self, other): return self.to_short(self.to_short(other)._x % self._x)
    def __rpow__(self, other): return self.to_short(self.to_short(other)._x ** self._x)
    def __rand__(self, other): return self.to_short(self.to_short(other)._x & self._x)
    def __rxor__(self, other): return self.to_short(self.to_short(other)._x ^ self._x)
    def __ror__(self, other): return self.to_short(self.to_short(other)._x | self._x)
    def __rlshift__(self, other): return self.to_short(self.to_short(other)._x << self._x)
    def __rrshift__(self, other): return self.to_short(self.to_short(other)._x >> self._x)
    def __int__(self): return int(self._x)
    def __float__(self): return float(self._x)
    def __neg__(self): return self.to_short(self._x.__neg__())
    def __pos__(self): return self
    def __abs__(self): return self
    def __invert__(self): return self.to_short(self._x.__invert__())

А затем просто измените ваш компьютер для использования нового класса.

def compute(data, datalen):
    crc=UShort(0xFFFF)
    for i in range(0, datalen):
        crc = (crc >> 8) | (crc << 8)
        crc = crc ^ data[i]
        crc = crc ^ ((crc & 0xff) >> 4)
        crc = crc ^ ((crc << 8) << 4)
        crc = crc ^ (((crc & 0xff) << 4)<<1)

    return crc.hex

data = [0x8c, 0x4c]
compute(data, 2)
# returns:
'0xcab2'
...