【发布时间】:2018-12-01 17:46:05
【问题描述】:
考虑以下人为的 Cython 函数来加入字符串列表:
# cython: language_level=3
cpdef test_join():
""" ["abc", "def", "ghi"] -> "abcdefghi" """
cdef:
list lines = ["abc", "def", "ghi"]
char* out = ""
char* line = ""
int i
for i in range(len(lines)):
line = lines[i]
out = out + line
return out
编译失败,报错:
存储临时 Python 引用的不安全 C 派生词
我假设这与 line 的类型为 char* 并不断重新分配有关。我已经看到了similar question 的答案,但无法针对这个基本示例修改该答案。 (而且它还涉及大量我不熟悉的 C-API。)
如何修改上面的函数才能按预期编译返回?
更广泛地说,我想更好地理解这个错误。 commit37e4a20有一点解释:
从临时 Python 字符串对象中获取
char*... 仅当将此类指针分配给变量并因此会超过字符串本身的生命周期时才会引发编译时错误。
更新:为了进一步简化,看起来问题是由分配引起的:
cpdef int will_succeed():
cdef char* a = b"hello"
cdef char* b = b" world"
print(a + b) # no new assignment
return 1
cpdef will_fail():
cdef char* a = b"hello"
cdef char* b = b" world"
a = a + b # won't compile
return a
我怀疑使用string.pxd/string.h 的东西可能有更合适的方法,但我在 C 内存管理和效率方面相当薄弱:
from libc.string cimport strcat, strcpy
cpdef use_strcat():
cdef char out[1024]
strcpy(out, b"")
cdef char* a = b"hello"
cdef char* b = b" world"
strcat(out, a)
strcat(out, b)
return out
【问题讨论】:
标签: cython