C数组到PyArray

Dan*_*oni 11 python numpy python-c-api python-c-extension

我在不使用Cython的情况下编写Python C-Extension.

我想在C中分配一个double数组,在内部函数中使用它(恰好在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);
}
Run Code Online (Sandbox Code Playgroud)

我调试了这段代码,当我尝试从a创建alpha时,我遇到了Segmentation错误.到那里一切正常.功能drecur_工作,如果删除它我会遇到同样的问题.

现在,围绕C数据定义PyArray的标准方法是什么?我找到了文档,但没有很好的例子.还有,内存泄漏怎么样?返回之前INCREF是否正确,以便保留alpha和beta的实例?那些不再需要的解除分配怎么样?

编辑 我终于用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 */
}
Run Code Online (Sandbox Code Playgroud)

随意评论这个并感谢您的答案.

cou*_*nt0 1

一个问题可能是您的数组 (a,b) 必须至少与包含它的 numpy 数组一样长。您已在本地范围内创建了数组,因此当您离开该方法时它们将被销毁。

尝试让 python 分配数组(例如使用PyArray_SimpleNew),将内容复制到其中并传递给它一个指针。如果可以选择针对 boost 进行构建,您可能还想使用boost::python来处理这些细节。