数据在c和python之间损坏

数据在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

我试图使用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;  
}
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