将带有内部空字符的 python2.7 字符串传递给 C++
Passing a python2.7 string with internal null characters to c++
有没有办法将中间带有空字符的 python2.7 字符串(例如 foo[=11=]bar
)传递给 swig 绑定中的 C++ 代码?
python C bindings 提供了两个函数:PyString_AsString
和 PyString_AsStringAndSize
,但是这两个函数都是 return 空终止字符串。
正如 PyString_AsStringAndSize
的文档所说,它会保留内部空字符,除非您为 length
传递 NULL
。你显然不会这样做(因为如果你不知道长度,你就不能对带有内部空字符的字符串做任何事情)。
它确实确保了无论您是否需要一个空终止符,但如果这是不可接受的,它很容易处理:只需将它的长度 returns 减一。
因此,除非您担心 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[=10=]bar'
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
来防止它因为太聪明而制作了一个字符串,然后将其转换为一个数组,因为不允许使用指针算法。)
有没有办法将中间带有空字符的 python2.7 字符串(例如 foo[=11=]bar
)传递给 swig 绑定中的 C++ 代码?
python C bindings 提供了两个函数:PyString_AsString
和 PyString_AsStringAndSize
,但是这两个函数都是 return 空终止字符串。
正如 PyString_AsStringAndSize
的文档所说,它会保留内部空字符,除非您为 length
传递 NULL
。你显然不会这样做(因为如果你不知道长度,你就不能对带有内部空字符的字符串做任何事情)。
它确实确保了无论您是否需要一个空终止符,但如果这是不可接受的,它很容易处理:只需将它的长度 returns 减一。
因此,除非您担心 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[=10=]bar'
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
来防止它因为太聪明而制作了一个字符串,然后将其转换为一个数组,因为不允许使用指针算法。)