Je suis en train d'écrire une extension C de Python sans utiliser Cython.
Je veux allouer un tableau double en C, l'utiliser dans une fonction interne (qui se trouve être en Fortran) et le retourner. Je fais remarquer que l'interface C-Fortran fonctionne parfaitement 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);
}
J'ai débogué ce code et j'obtiens un défaut de segmentation lorsque j'essaie de créer un alpha à partir de a. Jusque là, tout fonctionne bien. La fonction drecur_ fonctionne et j'obtiens le même problème si elle est supprimée.
Maintenant, quelle est la manière standard de définir un PyArray autour de données C ? J'ai trouvé de la documentation mais pas de bon exemple. De plus, qu'en est-il des fuites de mémoire ? Est-il correct d'INCREF avant le retour pour que les instances de alpha et beta soient préservées ? Qu'en est-il de la désallocation lorsqu'ils ne sont plus nécessaires ?
EDIT J'ai finalement réussi avec l'approche trouvée dans Livre de recettes NumPy .
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 */
}
N'hésitez pas à faire des commentaires à ce sujet et merci pour les réponses.