Нужна помощь в переносе функции C на Python

1

Я пытаюсь передать функцию 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;
  • 1
    Вы уверены, что line не содержит объект unicode , а, скорее, str (при условии, что вы на Python 2.x)? Тот факт, что вы % 256 в результате ord() выглядит подозрительно - для обычной строки ord() никогда не должно возвращать ничего за пределы диапазона от 0 до 255 .
  • 0
    строка должна быть простой строкой ascii, я на Python 2.7
Показать ещё 4 комментария
Теги:

3 ответа

4

Вот как вы можете настроить тестовую среду для диагностики вашей проблемы.

  1. Скопируйте приведенную выше функцию C в файл, удалите строку assert() и скомпилируйте ее в общую библиотеку с помощью

    gcc -shared -o checksum.so checksum.c
    

    (Если вы находитесь в Windows или что-то еще, выполните эквивалент выше).

  2. Скопируйте этот код в файл 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))

Обратите внимание, что эти реализации должны делать то же самое, что и ваши.

0

Вы проверили этот рецепт поваренной книги? В нем намекает, какой ввод вы должны включить в строку, возвращает звездочку перед контрольной суммой и дает одну (входную, выходную) пару данных, которую вы можете использовать в качестве тестовых данных.

Вы уверены, что "приемник" работает правильно? Является ли проблема из-за верхних и нижних строчных шестнадцатеричных букв?

-4

Альтернативой было бы расширение python -which, которое было специально разработано для расширения пользовательскими функциями C. Это означает, что вам нужно написать некоторый код слияния между вашей C-функцией и интерпретатором Python. SWIG может помочь вам (частично) генерировать код клея.

Расширение Python в основном имеет смысл для сильно используемых функций. Это полезно для функции, называемой миллионы раз, или работает как минимум на несколько миллисекунд.

PS. Извините за неправильное упоминание PHP в моей первой версии этого ответа.

  • 2
    Wut? О каком PHP вы говорите?
  • 1
    Этот вопрос касается Python, а не PHP.
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню