需要帮助将C函数移植到Python

时间:2011-11-27 19:32:59

标签: python c

我正在尝试移植一个计算GPS校验和到Python的C函数。根据接收端,我有时会错误地计算校验和,因此必须在那里有一个错误。

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;

3 个答案:

答案 0 :(得分: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;
    
  3. 现在您可以访问校验和功能的两个版本,并可以比较结果。我无法找到任何差异。

    (顺便说一下,你如何计算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))
    

    请注意,这些实现应与您的实现完全相同。

答案 1 :(得分:0)

你签出了this cookbook recipe吗?它暗示您应该在“line”中包含哪些输入,在校验和前面返回一个星号,并提供一个(输入,输出)数据对,您可以将其用作测试数据。

你确定“接收器”工作正常吗?问题是由大写和小写的十六进制字母引起的吗?

答案 2 :(得分:-3)

另一种选择是扩展 python - 它被设计为由自定义C函数扩展。这意味着您需要在C函数和Python解释器之间编写一些glue codeSWIG可以通过(部分)生成粘合代码来帮助您。

扩展Python主要适用于频繁使用的函数。对于一个数百万次的函数或者至少运行几毫秒的函数来说是值得的。

PS。很抱歉在我的第一个版本的答案中错误地提到了PHP。