Función Cython que genera un fallo de segmentación al llamar desde Python
Así que estoy intentando hacer un script que clonará algunos valores en una matriz 2D y dado que la matriz puede ser enorme, estoy utilizando cython, por cierto, soy nuevo en cython. Aquí está el código
from cpython cimport *
def cloningNodes(matrix,toClone):
cdef Py_ssize_t matrixSize=PyList_Size(matrix),cloneSize=PyList_Size(toClone),newSize=matrixSize+cloneSize,i,j
output=PyList_New(newSize)
for i in range(matrixSize):
PyList_SET_ITEM(output,i,
<object>PyList_GET_ITEM(matrix,i))
for j in range(cloneSize):
currentRow=<object>PyList_GET_ITEM(output,i)
PyList_Append(currentRow,<object>PyList_GET_ITEM(
<object>PyList_GET_ITEM(matrix,i),PyLong_AsSsize_t(<object>PyList_GET_ITEM(toClone,j))
)
)
for i in range(cloneSize):
PyList_SET_ITEM(output,i+matrixSize,<object>PyList_GET_ITEM(output,PyLong_AsSsize_t(<object>PyList_GET_ITEM(toClone,i))))
return output
Después de compilar y llamar a este módulo con
from MODULE_NAME import cloningNodes
cloningNodes([[1,2],[2,1]],[1])
Me está dando una falla de segmentación (CoreDumped). ¿Alguien puede decirme por qué está dando una falla de segmentación junto con cualquier mejora menor que pudiera encontrar?
Edit: Por cierto, intenté poner una declaración de impresión antes de return output y parece que la lista se crea sin problemas, pero hay algún problema al devolver la lista.
davy.ai
El código parece tener algunos problemas que pueden causar un fallo de segmentación. Aquí hay algunas sugerencias para mejorar el código:
[:]
) que creará una copia nueva de la lista.Al usar
PyList_SET_ITEM
oPyList_GET_ITEM
, debes llamar aPy_INCREF
yPy_DECREF
, respectivamente, para aumentar y disminuir el recuento de referencias del objeto. Esto es importante porque Python utiliza el recuento de referencias para realizar un seguimiento de la propiedad del objeto y para desasignar objetos no utilizados.Al acceder a un elemento en una lista anidada, debes utilizar
PyList_GET_ITEM
oPyList_SET_ITEM
para obtener o establecer un elemento. Sin embargo, no debes convertir el resultado a un tipo<object>
porque no es un tipo válido de Python. En su lugar, puedes utilizarPyLong_AsLong
para convertir el valor a un entero de Python.Con estas sugerencias, aquí hay una versión mejorada del código:
En esta versión, el código utiliza una comprensión de lista para crear una nueva copia de cada fila en la
matrix
. También verifica si el índice entoClone
está dentro del rango antes de clonar la fila. Para acceder a un elemento en una lista anidada, utilizaPyList_GET_ITEM
yPyLong_AsLong
para convertir el índice a un entero de Python.¡Espero que esto ayude!