作为的文档
PyString_AsStringAndSize
也就是说,除非传递,否则它会保留内部空字符
NULL
对于
length
。这显然是不可能做到的(因为如果不知道长度,就无法处理包含内部空字符的字符串)。
不管您是否需要,它都会确保在结尾处有一个空终止符,但如果不能接受,那么很容易处理:只需将它返回的长度减少一。
因此,除非您担心Python复制缓冲区只是为了添加一个不需要的空终止符的潜在性能成本(在这种情况下,我不会担心大多数创建字符串的方法,您已经在缓冲区中有了终止符),否则这里应该没有任何问题。
为了证明这一点:
#!/usr/bin/env python2.7
from ctypes import *
PyString_AsStringAndSize = pythonapi.PyString_AsStringAndSize
PyString_AsStringAndSize.argtypes = [
py_object, POINTER(POINTER(c_int8)), POINTER(c_ssize_t)]
PyString_AsStringAndSize.restype = c_int
s = 'foo\0bar'
buf = POINTER(c_int8)()
size = c_ssize_t()
res = PyString_AsStringAndSize(s, byref(buf), byref(size))
print res
print size.value
bufa = cast(buf, POINTER(c_int8 * size.value))
print bufa.contents[:size.value]
print repr(''.join(chr(c) for c in bufa.contents[:size.value]))
输出为:
0
7
[102, 111, 111, 0, 98, 97, 114]
'foo\x00bar'
正是你想要的,对吧?
(而且在C++中,您不必做那些烦人的事情来解决问题
ctypes
我做到了,首先使用
int8
而不是
char
防止它太聪明,生成字符串,然后将其强制转换为数组,因为不允许使用指针算法。)