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
是一大块内存,因此复制工作正常。
我在将二维数组从 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
是一大块内存,因此复制工作正常。