将带有内部空字符的python2.7字符串传递给c ++

Posted

技术标签:

【中文标题】将带有内部空字符的python2.7字符串传递给c ++【英文标题】:Passing a python2.7 string with internal null characters to c++ 【发布时间】:2018-03-13 03:01:19 【问题描述】:

有没有办法将中间有空字符的python2.7字符串(例如foo\0bar)传递给swig绑定中的c++代码?

python C bindings 提供两个函数:PyString_AsStringPyString_AsStringAndSize,但两个函数都返回以 null 结尾的字符串。

【问题讨论】:

【参考方案1】:

正如PyString_AsStringAndSize 的文档所说,它保留内部空字符,除非您将NULL 传递给length。你显然不会这样做(因为如果你不知道长度,你不能对带有内部空字符的字符串做任何事情)。

不管你是否想要一个空终止符,它确实确保最后有一个空终止符,但如果这是不可接受的,它很容易处理:只需将它返回的长度减一。

所以,除非您担心 Python 复制缓冲区的潜在性能成本只是为了添加您不需要的空终止符(在这种情况下,我不会担心 - 大多数创建字符串的方法,您re 已经在缓冲区中有终止符),这里应该没有任何问题。


证明:

#!/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 以防止它太聪明并制作字符串,然后将其转换为数组,因为不允许使用指针运算。)

【讨论】:

以上是关于将带有内部空字符的python2.7字符串传递给c ++的主要内容,如果未能解决你的问题,请参考以下文章

如何将 C# 类字符串变量传递给 sbyte* 参数?

将可写 StringBuilder 数组从 C# 传递给 C++

通过引用将字符串数组传递给 C 函数

在 Python 2.7.1 中使用 itertools、yield 和 iter() 生成带有滑动窗口的字符串列表?

C ++将文件行传递给字符串向量

如何将包含撇号的字符串传递给android中的查询?