numpy.i是否将实际的指针发送到C ++,或制作内存副本?

时间:2019-06-19 20:22:48

标签: python c++ numpy swig numpy-ndarray

我正在为我正在从事的实验室学习C ++,swig和numpy。已指定必须使用swig(无scypy),必须使用numpy数组,并且我可能不会“将C代码带入python世界”,例如在接口文件中使用%import“ std_vector”,然后让python用户创建一个要发送的文件。也就是说,我正在尝试获取一维numpy数组(如果它们需要更多尺寸,我会只是将其展平)以专门通过指针传递到我的C代码中-我的老板不想花时间复制所有内容,因为效率非常重要。我相信我们使用的是c ++ 14,python 2.7和最新版本的swig,我也使用了numpy.i。

我将在下面提供我当前正在使用的代码(只是试图在此处获得最小的可行性),但是我还很新,虽然它确实起作用,但我不确定它实际上是在传递指针而不进行复制像我想要的任何东西。有人可以确认它是什么,还是告诉我如何做到这一点?谢谢x10 ^ 99

com.domain.project

这将编译并运行,并创建一个可以正常工作的python模块,当我在同一目录中导入时,“从np_array_to_array import *”,我可以成功运行getMid方法,传入numpyArray并获取一个double退出。如上所述,我根本不确定这是否实际上是通过指针传递的(不进行任何复制),因为我还没有发现任何一种或另一种方式。有人可以告诉我,如果不是,请解释一个人该怎么做?我认为这应该是可行的,因为我认为numpy数组会使用c类型并像c那样连续存储内存。

1 个答案:

答案 0 :(得分:1)

您可以在SWIG生成的代码中对此进行轻松调查。这有两个部分-.py文件和.cxx文件。在以上每种方法中,都会为您的getMid()函数生成一些代码。 Python代码只是将所有内容直接传递到C ++代码中,在我的系统上最终看起来像这样:

SWIGINTERN PyObject *_wrap_getMid(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
  PyObject *resultobj = 0;
  double *arg1 = (double *) 0 ;
  int arg2 ;
  PyArrayObject *array1 = NULL ;
  int is_new_object1 = 0 ;
  PyObject * obj0 = 0 ;
  double result;

  if (!PyArg_ParseTuple(args,(char *)"O:getMid",&obj0)) SWIG_fail;
  {
    npy_intp size[1] = {
      -1 
    };
    array1 = obj_to_array_contiguous_force_conversion(obj0, NPY_DOUBLE,
      &is_new_object1);
    if (!array1 || !require_dimensions(array1, 1) ||
      !require_size(array1, size, 1)) SWIG_fail;
    arg1 = (double*) array_data(array1);
    arg2 = (int) array_size(array1,0);
  }
  result = (double)getMid(arg1,arg2);
  resultobj = SWIG_From_double(static_cast< double >(result));
  {
    if (is_new_object1 && array1)
    {
      Py_DECREF(array1); 
    }
  }
  return resultobj;
fail:
...

在SWIG和Python版本之间,它不会有太大变化,尽管某些SWIG选项会对其进行一些更改。

从您的问题的角度来看,重点似乎是对obj_to_array_contiguous_force_conversion的呼吁。它有一个参数用作输出参数,以指示是否分配了新对象。如果最终将其设置为true,则在调用之后,对象也将最终被释放。

仅凭这一点就可以得出结论,问题的答案是取决于您传递给函数的输入内容是非常安全的。如果它已经满足约束条件(即它是连续的),那么您将不会最终制作副本。否则,因为您的C ++函数需要一个连续的区域。

应该确信,如果您使用任何numpy double类型,那么最终将满足此要求并且不进行复制,但是对于其他数据类型,除非您使用了一点努力。