我在cdef对象中有以下cython代码:
def __getstate__(self):
cdef char *bp
cdef size_t size
cdef cn.FILE *stream
stream = cn.open_memstream(&bp, &size)
cn.write_padded_binary(self.im, self.n, 256, stream)
cn.fflush(stream);
cn.fclose(stream)
print("pointer", bp, "size_t:", size)
# ('pointer', b'', 'size_t:', 6144)
bt = c.string_at(bp, size)
print("bt", bt)
cn.free(bp)
return bt
但是,print("pointer", bp, "size_t:", size)
中打印的指针和print("bt", bt)
中打印的字节串让我担心出现问题。指针只是('pointer', b'', 'size_t:', 6144)
,而bytestring似乎包含来自Python源代码的文本:
x00 \ x00规范化编码名称。\ n \ n规范化的作用如下 如下:除了使用的点之外的所有非字母数字\ n字符 对于Python包名称是\ n折叠并替换为 单个下划线,例如\' - ;#\' \ n变为\' _ \'。领导和 删除尾随下划线。\ n \ n请注意编码名称 应该只是ASCII;如果他们确实使用\ n非ASCII字符, 这些必须是Latin-1兼容的。\ n \ n \ x00 \ x00 \
(它主要只是字节符号)。
我确定write_padded_binary_works
,因为当我给它一个常规文件描述符时它会起作用。我也确定open_memstream有效,因为当我使用cn.fprintf(stream, "hello");
而不是write_padded_binary
进行尝试时,输出为('bt', b'hello')
。但是,指针也是('pointer', b'hello', 'size_t:', 5)
所以我必须误解一些与指针相关的东西我认为......
答案 0 :(得分:1)
您遇到的问题(被诊断为elsewhere)是您无法将char*
直接传递给Python函数。当您做Cython尝试将其转换为字符串时(这没有意义,因为它只是保存二进制数据,因此将其解释为空终止的C字符串会导致它读取任意长度,直到找到0。
这种情况与print
和ctypes.string_at
都有问题。两种情况下的技巧是首先将其转换为适当大小的整数。保证C uintptr_t
足够大以容纳整数,因此是合适的选择:
from libc.stdint cimport uintptr_t
print("pointer", <uintptr_t>bp, "size_t:", size)
bt = c.string_at(<uintptr_t>bp, size)