【问题标题】:Python C Api: transfer dynamically allocated array to Python [duplicate]Python C Api:将动态分配的数组传输到Python [重复]
【发布时间】:2016-10-19 06:56:00
【问题描述】:

我正在使用 Python,我想对巨大的数组(大小可达8000 x 500)。为了加快速度,我在 C 中实现了该例程。我使用 Python C API 将数据传递给 C,进行计算,然后将其发回。 由于涉及到这么大的数组,所以我使用动态内存分配来存储计算结果(标记为R,见代码)。

现在我无法将此数组发送回 Python。目前我正在使用 Py_BuildValue (见代码)。构建 .pyd 扩展是可行的,但是当我执行 Python 代码时,我收到消息“python.exe 停止工作”。

我想问一下,您是否可以帮助我以正确的方式实现它:) [我在代码中省略了一些变量,使其更短一些]

# include <stdlib.h>
# include <stdio.h>
# include <math.h>
# include <Python.h>
# include <numpy\arrayobject.h>

static PyObject* integrateODE(PyObject* self, PyObject* args);
double func ( double t, double u , double a );

int Nt, Nr, m;
double dt, rho0, eta1, eta2, rho2decay;

static PyObject* integrateODE(PyObject* self, PyObject* args)
  {  
  int i,k, len;
  double *mag;
  double u, u0, u1,u2,u3 ;  
  double a0, a1;  
  double f0, f1, f2, f3;
  PyObject *U;
  double *R;

  PyArg_ParseTuple(args, "Offifffii", &U, &dt, &rho0, &m, &eta1, &eta2,&rho2decay, &Nt, &Nr);  
  R = malloc(sizeof(double) * Nt*Nr);  
  len = PySequence_Length(U); 
  mag= malloc(sizeof(double) * Nt*Nr);

  while (len--) {  
  *(mag + len) = (double) PyFloat_AsDouble(PySequence_GetItem(U, len)); 
  }

  for (k=0; k<Nr; k++ )
    {
     u0 = rho0;
     for (i=0; i<Nt; i++ )
         {
          a0=mag[k*Nt + i];
          a1=mag[k*Nt + i+1];
          f0 = func( t0, u0, a0 );
          u1 = u0 + dt * f0 / 2.0;            
          f1 = func( t1, u1, a1 );
          u2 = u0 + dt * f1 / 2.0;  
          f2 = func( t2, u2, a1 );    
          u3 = u0 + dt * f2;
          f3 = func( t3, u3, a0 );
          u = u0 + dt * ( f0 + 2.0 * f1 + 2.0 * f2 + f3 ) / 6.0;    
          R[k*Nt + i] = u;
          u0 = u;       
          }           
     }

     return Py_BuildValue("O", R);
}

double func ( double t, double u, double a ){
  dydt = -u*u  +  a * u + a;  
  return dydt;
}
static PyMethodDef ODE_Methods[] =
{
 {"integrateODE", integrateODE, METH_VARARGS, NULL}, 
 {NULL, NULL, 0, NULL} 
};

PyMODINIT_FUNC initodeNRP(void) {
(void) Py_InitModule("odeNRP", ODE_Methods);
}

非常感谢您能给我的任何帮助:)

【问题讨论】:

  • 嗨,大卫,感谢您的链接。直接修改numpy数组的有趣想法,根本不传递数组。我会试试这个:)
  • 你也可以自己创建numpy数组docs.scipy.org/doc/numpy/user/…。无论哪种方式 numpy 都是要走的路
  • 谢谢大卫,我设法让它工作了!

标签: python c python-c-api


【解决方案1】:

在你的分配中,:

mag size = Nt*Nr,

在您的循环中,当 i 为最大值且 k 为最大值时:

k=Nr-1, i=Nt-1, 

因此:

a0=mag[k*Nt + i]; -> (Nt-1)+Nt*(Nr-1)=Nt-1+NtNr-Nt=NtNr-1,然后你打电话

a1=mag[k*Nt + i+1];, (Nt-1)+Nt*(Nr-1)+1=Nt-1+NtNr-Nt+1=NtNr 这是NtNr -> 越界

您也可以尝试使用PyList_New(length);PyArray_SimpleNewFromData(nd, dims, NPY_DOUBLE, a); 来返回您的数组。

【讨论】:

  • 您好 Anatoly,非常感谢您 - Davids 和您的方法都有效。问这么简单的问题我觉得很愚蠢,但有时一些指导会产生奇迹:)
  • 没问题!祝你好运!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-13
  • 1970-01-01
相关资源
最近更新 更多