代码之家  ›  专栏  ›  技术社区  ›  ead

是ByteArray结尾所必需的显式NUL字节,Cython才能将其转换为以空结尾的C字符串

  •  1
  • ead  · 技术社区  · 8 年前

    当转换 bytearray -对象(或 bytes -对象)转换为C字符串时, cython-documentation 建议使用以下方法:

    cdef char * cstr = py_bytearray
    

    没有开销,因为 cstr 指向的缓冲区 Bytearray公司 -反对。

    但是,c字符串是 null-terminated 因此为了能够通过 CSTR 对于c函数,它也必须以空结尾。cython文档不提供任何信息,不管生成的c字符串是否以空结尾。

    可以添加 NUL -字节显式到 byarray -对象,例如使用 b'text\x00' 而不仅仅是“b”文本。但这很麻烦,很容易忘记,而且至少有实验证据表明,不需要显式的nul字节:

    %%cython
    from libc.stdio cimport printf
    def printit(py_bytearray):
        cdef char *ptr = py_bytearray
        printf("%s\n", ptr)
    

    现在

    printit(bytearray(b'text'))
    

    将所需的“文本”打印到stdout(在ipython笔记本的情况下,这显然不是浏览器中显示的输出)。

    但这是一个幸运的巧合还是有保证,bytearray对象(或bytes对象)的缓冲区是以空结尾的?

    1 回复  |  直到 8 年前
        1
  •  2
  •   DavidW    8 年前

    我认为它是安全的(至少在python 3中是这样),但是我会有点谨慎。

    cython使用c-api函数 PyByteArray_AsString . 这个 Python3 documentation for it 表示“返回的数组总是附加一个额外的空字节。” Python2 version 没有那张纸条所以很难确定它是否安全。

    实际上,我认为python处理这个问题的方法是总是将bytearray过度分配一个,并将其终止为空(参见 source code 举一个这样做的例子)。

    唯一需要谨慎的原因是bytearray(以及python字符串)完全可以接受在字符串中包含0字节,因此它不是一个很好的结束位置指示器。因此,您应该真正使用 len 无论如何。(这是一个很弱的论点,特别是因为你可能是初始化它们的人,所以你知道这是否应该是真的)


    (我最初的回答是关于 _PyByteArray_empty_string . @ead在评论中指出,我错了,因此删掉了……)

    推荐文章