Escribo una extensión C de Python sin utilizar Cython.C array a PyArray
Quiero asignar una matriz doble en C, usarla en una función interna (que está en Fortran) y devolverla. Señalo que la interfaz C-Fortran funciona perfectamente en C.
static PyObject *
Py_drecur(PyObject *self, PyObject *args)
{
// INPUT
int n;
int ipoly;
double al;
double be;
if (!PyArg_ParseTuple(args, "iidd", &n, &ipoly, &al, &be))
return NULL;
// OUTPUT
int nd = 1;
npy_intp dims[] = {n};
double a[n];
double b[n];
int ierr;
drecur_(n, ipoly, al, be, a, b, ierr);
// Create PyArray
PyObject* alpha = PyArray_SimpleNewFromData(nd, dims, NPY_DOUBLE, a);
PyObject* beta = PyArray_SimpleNewFromData(nd, dims, NPY_DOUBLE, b);
Py_INCREF(alpha);
Py_INCREF(beta);
return Py_BuildValue("OO", alpha, beta);
}
I depurado el código y me da un fallo de segmentación cuando intento crear alfa de una. Hasta allí todo funciona bien. La función drecur_ funciona y obtengo el mismo problema si se elimina.
Ahora, ¿cuál es la forma estándar de definir un PyArray en torno a los datos C? Encontré documentación pero no un buen ejemplo. Además, ¿qué pasa con la pérdida de memoria? ¿Es correcto INCREF antes del retorno para que se conserve la instancia de alfa y beta? ¿Qué pasa con la desasignación cuando ya no son necesarios?
EDITAR finalmente lo hizo bien con el enfoque que se encuentra en NumPy cookbook.
static PyObject *
Py_drecur(PyObject *self, PyObject *args)
{
// INPUT
int n;
int ipoly;
double al;
double be;
double *a, *b;
PyArrayObject *alpha, *beta;
if (!PyArg_ParseTuple(args, "iidd", &n, &ipoly, &al, &be))
return NULL;
// OUTPUT
int nd = 1;
int dims[2];
dims[0] = n;
alpha = (PyArrayObject*) PyArray_FromDims(nd, dims, NPY_DOUBLE);
beta = (PyArrayObject*) PyArray_FromDims(nd, dims, NPY_DOUBLE);
a = pyvector_to_Carrayptrs(alpha);
b = pyvector_to_Carrayptrs(beta);
int ierr;
drecur_(n, ipoly, al, be, a, b, ierr);
return Py_BuildValue("OO", alpha, beta);
}
double *pyvector_to_Carrayptrs(PyArrayObject *arrayin) {
int n=arrayin->dimensions[0];
return (double *) arrayin->data; /* pointer to arrayin data as double */
}
Siéntase libre de comentar sobre esto y gracias por las respuestas.