我正在尝试使用Cython和ctypes
使用Python调用c库函数。
但是数据字节不知怎么被破坏了。有人能帮忙找出问题所在吗?你知道吗
testCRC.c
:
#include <stdio.h>
unsigned char GetCalculatedCrc(const unsigned char* stream){
printf("Stream is %x %x %x %x %x %x %x\n",stream[0],stream[1],stream[2],stream[3],stream[4],stream[5],stream[6]);
unsigned char dummy=0;
return dummy;
}
wrapped.pyx
:
# Exposes a c function to python
def c_GetCalculatedCrc(const unsigned char* stream):
return GetCalculatedCrc(stream)
test.py
:
x_ba=(ctypes.c_ubyte *7)(*[0xD3,0xFF,0xF7,0x7F,0x00,0x00,0x41])
x_ca=(ctypes.c_char * len(x_ba)).from_buffer(x_ba)
y=c_GetCalculatedCrc(x_ca.value)
输出:
Stream is d3 ff f7 7f 0 0 5f # expected 0xD3,0xFF,0xF7,0x7F,0x00,0x00,0x41
解决方案:
1。 我不得不将cython更新为0.29,以修复不允许使用类型化内存的错误(只读问题)。你知道吗
2。 它通过了x_生的. 但是当x_ca.价值已传递,但抛出错误“越界访问”
根据@ead&;DavidW的建议:
´.pyx´:
def c_GetCalculatedCrc(const unsigned char[:] stream):
# Exposes a c function to python
print "received %s\n" %stream[6]
return GetCalculatedCrc(&stream[0])
''测试.py':
x_ba=(ctypes.c_ubyte *8)(*[0x47,0xD3,0xFF,0xF7,0x7F,0x00,0x00,0x41])
x_ca=(ctypes.c_char * len(x_ba)).from_buffer(x_ba)
y=c_GetCalculatedCrc(x_ca.raw)
输出:
Stream is 47 d3 ff f7 7f 0 0 41
正如@DavidW指出的,问题在于
x_ca.value
的用法:调用x_ca.value
时,每次创建新的bytes对象(请参见documentation)并复制内存时:但是,当复制内存时,它会将
\0
字符作为字符串的结尾(这对于C字符串是典型的),如source code所示:因此,
x_ca.value
的结果是一个长度为4
的bytes对象,它不与x_ca
共享内存—当您访问stream[6]
时,它会导致未定义的行为—任何事情都可能发生(也可能发生崩溃)。你知道吗那该怎么办呢?你知道吗
通常情况下,在} 实现的。你知道吗
def
函数中不能有指针参数,但char *
是一个例外bytes
对象可以自动转换为char *
,但这不是通过缓冲区协议而是通过^{这就是为什么不能将
x_ca
传递给c_GetCalculatedCrc
的原因:x_ca
实现缓冲区协议,但不是bytes
对象,因此没有PyBytes_AsStringAndSize
。你知道吗另一种方法是使用类型化内存视图,它利用缓冲区协议,即
现在直接传递
x_ca
,原始长度/内容:另一种方法是将
x_ca.raw
传递给期望const unsigned char *
作为参数的函数,正如@DavidW在注释中指出的那样,它与x_ca
共享内存。不过,我更喜欢类型化内存视图—它们比原始指针更安全,而且不会出现意外的未定义行为。你知道吗相关问题 更多 >
编程相关推荐