Python C 扩展

Python C Extension

我在将二维数组从 C 扩展返回到 Python 时遇到问题。当我使用 malloc 分配内存时,返回的数据是垃圾。当我刚刚初始化像 sol_matrix[nt][nvar] 这样的数组时,返回的数据符合预期。

#include <Python.h>
#include <numpy/arrayobject.h>
#include <math.h>
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION

// function to be solved by Euler solver
double func (double xt, double y){

    double y_temp = pow(xt, 2); 
    y = y_temp;

    return y;
}

static PyObject* C_Euler(double h, double xn)
{
    double y_temp, dydx;                //temps required for solver
    double y_sav = 0;                   //temp required for solver
    double xt = 0;                      //starting value for xt
    int nvar = 2;                       //number of variables (including time)
    int nt = xn/h;                      //timesteps
    double y = 0;                       //y starting value
            
    //double sol_matrix[nt][nvar];        //works fine
        
    double **sol_matrix = malloc(nt * sizeof(double*));  //doesn't work

    for (int i=0; i<nt; ++i){
        sol_matrix[i] = malloc (nvar * sizeof(double));
    }
    
    int i=0;
    
    //solution loop - Euler method.
    while (i < nt){

        sol_matrix[i][0]=xt;
        sol_matrix[i][1]=y_sav;
        dydx = func(xt, y);          
        y_temp = y_sav + h*dydx;
        xt = xt+h;
        y_sav=y_temp;
        i=i+1;   
    }

    npy_intp dims[2];
    dims[0] = nt;
    dims[1] = 2;
  
    //Create Python object to copy solution array into, get pointer to
    //beginning of array, memcpy the data from the C colution matrix 
    //to the Python object. 
    PyObject *newarray = PyArray_SimpleNew(2, dims, NPY_DOUBLE);
    double *p = (double *) PyArray_DATA(newarray);
    memcpy(p, sol_matrix, sizeof(double)*(nt*nvar));   
    

    // return array to Python
    
    return newarray;      
}

static PyObject* Euler(PyObject* self, PyObject* args)
{
    double h, xn;

    if (!PyArg_ParseTuple(args, "dd", &h, &xn)){
        
        return NULL;
    }
    return Py_BuildValue("O", C_Euler(h,xn));
}

您能否就我哪里出错提供任何指导?

谢谢。

sol_matrix中的数据不在连续内存中,它在nt单独分配的数组中。因此行

memcpy(p, sol_matrix, sizeof(double)*(nt*nvar));   

不会起作用。

我不是 pointer-to-pointer 数组的忠实粉丝所以相信你最好的选择是将 sol_matrix 分配为一个大块:

double *sol_matrix = malloc(nt*nvar * sizeof(double));

这意味着您不能进行 2D 索引,所以需要这样做

// OLD: sol_matrix[i][0]=xt;
sol_matrix[i*nvar + 0] = xt;

对比

double sol_matrix[nt][nvar];        //works fine

是一大块内存,因此复制工作正常。