Я пишу C-Extension Python без использования Cython.
Я хочу выделить двойной массив в C, использовать его во внутренней функции (которая находится в Fortran) и вернуть ее. Я отмечаю, что интерфейс C-Fortran отлично работает в 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);
}
Я отлаживал этот код, и я получаю ошибку сегментации, когда пытаюсь создать альфа из. Там все работает нормально. Функция drecur_ работает, и я получаю ту же проблему, если она удалена.
Теперь, каков стандартный способ определения PyArray вокруг данных C? Я нашел документацию, но не был хорошим примером. Также, как насчет утечки памяти? Правильно ли это для INCREF перед возвратом, чтобы сохранить экземпляр альфы и бета? Как насчет освобождения, когда они больше не нужны?
ИЗМЕНИТЬ Я, наконец, понял это с помощью подхода, найденного в кулинарной книге 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 */
}
Не стесняйтесь прокомментировать это и спасибо за ответы.