数据在c和python之间损坏
我试图使用Cython和数据在c和python之间损坏,python,cython,ctypes,Python,Cython,Ctypes,我试图使用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],strea
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;
}
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)
输出:
预计流量为d3 ff f7 F 0 0 5f
0xD3,0xFF,0xF7,0x7F,0x00,0x00,0x41
解决方案:
一,。
我不得不将cython更新为0.29,以修复不允许使用类型化内存的错误(只读问题)
二,。
它通过x_ca raw有效。但当传递x_ca.value时,抛出了错误“越界访问”
根据@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])
`test.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)
输出:
溪流为47 d3 ff f7 0 41
正如@DavidW所指出的,问题在于您对
x_ca.value
的使用:当调用x_ca.value
时,每次创建新的字节对象(请参阅)并复制内存时:
x_ca.value is x_ca.value
#False -> every time a new object is created
但是,当复制内存时,它会将\0
-字符处理为字符串的结尾(这是典型的C字符串),如图所示:
现在直接传递x_ca
,原始长度/内容:
c_GetCalculatedCrc(x_ca)
# 65 as expected
另一种选择是将
x_ca.raw
传递给期望const unsigned char*
作为参数的函数,正如@DavidW在注释中指出的那样,它与x_ca
共享内存。然而,我更喜欢类型化内存视图-它们比原始指针更安全,并且不会遇到意外的未定义行为。问题在于ctypes方面-尝试print(len(x_ca.value))
我认为缓冲区方法更好,但看起来x_ca.raw
将获得完整字符串。当知道正确的值时,.value
停在“\0”似乎是一个奇怪的选择size@DavidW你是对的。在文档中的某个地方,他们说:“当前内存块内容可以通过raw属性访问(或更改);如果您想以NUL终止的字符串形式访问它,请使用value属性:”这样看来,它是有意义的。但遗憾的是,在对价值属性的描述中没有提到它。我不得不将cython更新为0.29,以修复不允许使用类型化内存的错误(只读问题)。2.它通过x_ca raw有效。但是当x_ca.value被传递时,它抛出了错误“越界访问”。@DavidW..谢谢
static PyObject *
CharArray_get_value(CDataObject *self, void *Py_UNUSED(ignored))
{
Py_ssize_t i;
char *ptr = self->b_ptr;
for (i = 0; i < self->b_size; ++i)
if (*ptr++ == '\0')
break;
return PyBytes_FromStringAndSize(self->b_ptr, i);
}
%%cython
def c_GetCalculatedCrc(const unsigned char[:] stream):
print(stream[6]);
c_GetCalculatedCrc(x_ca)
# 65 as expected