Рассмотрим следующую придуманную функцию 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
Не удастся скомпилировать с этой ошибкой:
Хранение небезопасного производного C от временныхСсылка на Python
Я предполагаю, что это связано с line
, имеющим тип char*
и постоянно переназначаемым.Я видел ответ на подобный вопрос , но не смог изменить этот ответ для этого базового примера.(И это также включает в себя большое количество C-API, с которым я не знаком.)
Как я могу изменить вышеуказанную функцию для компиляции и возврата в соответствии с ожиданиями?
В более широком смысле, я хочу лучше понять эту ошибку.Коммит 37e4a20 имеет несколько объяснений:
Получение char*
из временного строкового объекта Python ... Ошибка времени компиляции возникает, только когда такой указатель назначенпеременной и, следовательно, превысит время жизни самой строки.
Обновление : чтобы еще больше упростить ситуацию, похоже, что это назначение вызываетПроблема:
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