Я пытаюсь передать функцию C, которая вычисляет контрольную сумму GPS на Python. В соответствии с принимающей стороной я иногда ошибаюсь в контрольной сумме, поэтому у нее все еще есть ошибка.
C код
void ComputeAsciiChecksum(unsigned char *data, unsigned int len,
unsigned char *p1, unsigned char *p2)
{
unsigned char c,h,l;
assert(Stack_Low());
c = 0;
while (len--) {
c ^= *data++;
}
h = (c>>4);
l = c & 0xf;
h += '0';
if (h > '9') {
h += 'A'-'9'-1;
}
l += '0';
if (l > '9') {
l += 'A'-'9'-1;
}
*p1 = h;
*p2 = l;
}
Моя попытка использования функции Python
def calcChecksum(line):
c = 0
i = 0
while i < len(line):
c ^= ord(line[i]) % 256
i += 1
return '%02X' % c;
Вот как вы можете настроить тестовую среду для диагностики вашей проблемы.
Скопируйте приведенную выше функцию C в файл, удалите строку assert()
и скомпилируйте ее в общую библиотеку с помощью
gcc -shared -o checksum.so checksum.c
(Если вы находитесь в Windows или что-то еще, выполните эквивалент выше).
Скопируйте этот код в файл Python:
import ctypes
import random
c = ctypes.CDLL("./checksum.so")
c.ComputeAsciiChecksum.rettype = None
c.ComputeAsciiChecksum.argtypes = [ctypes.c_char_p, ctypes.c_uint,
ctypes.c_char_p, ctypes.c_char_p]
def compute_ascii_checksum_c(line):
p1 = ctypes.create_string_buffer(1)
p2 = ctypes.create_string_buffer(1)
c.ComputeAsciiChecksum(line, len(line), p1, p2)
return p1.value + p2.value
def compute_ascii_checksum_py(line):
c = 0
i = 0
while i < len(line):
c ^= ord(line[i]) % 256
i += 1
return '%02X' % c;
Теперь у вас есть доступ к обеим версиям функции контрольной суммы и вы можете сравнить результаты. Я не мог найти никаких различий.
(Кстати, как вы вычисляете длину строки в C? Если вы используете strlen()
, это остановится на NUL байтах.)
В качестве побочной заметки ваша версия Python не является действительно идиоматическим Python. Вот еще две идиоматические версии:
def compute_ascii_checksum_py(line):
checksum = 0
for c in line:
checksum ^= ord(c)
return "%02X" % checksum
или
def compute_ascii_checksum_py(line):
return "%02X" % reduce(operator.xor, map(ord, line))
Обратите внимание, что эти реализации должны делать то же самое, что и ваши.
Вы проверили этот рецепт поваренной книги? В нем намекает, какой ввод вы должны включить в строку, возвращает звездочку перед контрольной суммой и дает одну (входную, выходную) пару данных, которую вы можете использовать в качестве тестовых данных.
Вы уверены, что "приемник" работает правильно? Является ли проблема из-за верхних и нижних строчных шестнадцатеричных букв?
Альтернативой было бы расширение python -which, которое было специально разработано для расширения пользовательскими функциями C. Это означает, что вам нужно написать некоторый код слияния между вашей C-функцией и интерпретатором Python. SWIG может помочь вам (частично) генерировать код клея.
Расширение Python в основном имеет смысл для сильно используемых функций. Это полезно для функции, называемой миллионы раз, или работает как минимум на несколько миллисекунд.
PS. Извините за неправильное упоминание PHP в моей первой версии этого ответа.
line
не содержит объектunicode
, а, скорее,str
(при условии, что вы на Python 2.x)? Тот факт, что вы% 256
в результатеord()
выглядит подозрительно - для обычной строкиord()
никогда не должно возвращать ничего за пределы диапазона от0
до255
.