代码之家  ›  专栏  ›  技术社区  ›  Justin Raymond

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

  •  1
  • Justin Raymond  · 技术社区  · 6 年前

    是否有方法传递中间有空字符的python2.7字符串(例如 foo\0bar )到swig绑定中的c++代码?

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

    1 回复  |  直到 6 年前
        1
  •  1
  •   abarnert    6 年前

    作为的文档 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 防止它太聪明,生成字符串,然后将其强制转换为数组,因为不允许使用指针算法。)