在一些生物物理模型的模拟框架内,我有一个C ++类,它使用需要返回PyArrayObject*
的成员函数来实现我的模型。该类在头文件ng_networks.h
中定义,其类似于:
#include <stdio.h>
#include <math.h>
#include <Python.h>
#include <numpy/arrayobject.h> /* Numpy as seen from C */
struct ngn{...}; /* Structure of model parameter */
class ngn_rate{ /* Model Class */
int NEQ;
ngn pars;
double *y,*dy;
public:
ngn_rate(); // Constructor
~ngn_rate(); // Destructor
PyObject* bifsystem();
}
ngn_rate::ngn_rate(){
// Set ngn pars default values
...
// Allocate memory for model variables and RHS of equations
y = (double*)calloc(NEQ,sizeof(double));
dy = (double*)calloc(NEQ,sizeof(double));
}
ngn_rate::~ngn_rate{
free(y);
free(dy);
}
PyObject* ngn_rate::bifsystem(){
long int NUMEL = NEQ; // PyArray creation function requires (long int*)
// Does some operations on y,dy
...
// Build PyObject* from dy
// Create Python Array Object...
PyObject* out_array = PyArray_SimpleNew(1,&NUMEL,NPY_DOUBLE);
// ... and make C pointer to point to it
double* dy_aux = (double*)((PyArrayObject*)out_array)->data;
// Copy dy into PyObject out_array
for(int i=0;i<NUMEL;i++) dy_aux[i] = dy[i];
return out_array;
}
你可能会猜到这个类最终是从Python模块中调用的。在这方面,我使用scipy.weave将我的C代码与Python接口。所以调用Python模块看起来像:
def ngn_rate_py():
support_code = """
#include <Python.h>
#include "ng_networks.h"
"""
source_files = [...] # A list of C/CPP source file names
libs = ['m']
dirs = [...] # A list of #include dirs
# My C code to interface with Python
code = """
//Initialize Model
ngn_rate network();
//Return dy_dt
return_val = network.bifsystem();
"""
vars = []
dy = weave.inline(code,
vars,
support_code = support_code,
sources = source_files,
libraries = libs,
library_dirs = dirs,
include_dirs = dirs,
runtime_library_dirs = dirs,
type_converters = converters.blitz,
compiler = 'gcc',
extra_compile_args = ['-std=c++11'],
force = 1)
return dy
当我运行上述模块时,它会产生分段错误。经过一些调试和反复试验后,我发现PyObject* out_array
中ng_networks.h
的初始化导致问题是由于某种原因造成的。确实,当我在PyObject*
中的C代码中创建weave
时,它完美地工作:即我修改ngn_rate::bifsystem()
类成员函数,使其返回double*
,然后构建编织界面中后者的PyObject*
:
class ngn_rate{ /* Model Class */
...
public:
...
double* bifsystem();
}
double* ngn_rate::bifsystem(){
long int NUMEL = NEQ; // PyArray creation function requires (long int*)
// Does some operations on y,dy
...
return dy;
}
然后在weave
界面:
def ngn_rate_py():
support_code = """
#include <Python.h>
#include "ng_networks.h"
"""
code = """
//Initialize Model
ngn_rate network();
//Create temporary dy
double *dy = network.bifsystem();
//Create PyObject*
PyObject* out_array = PyArray_SimpleNew(1, &NUMEL, NPY_DOUBLE);
double* dy_aux = (double*) ((PyArrayObject*) out_array)->data;
//Assign dy to PyObject
for(int i=0;i<NUMEL;i++) dy_aux[i]=dy[i];
return_val = out_array;
我无法弄清楚上面的原因是什么,而如果我让班级返回PyObject*
,我会遇到分段错误。值得注意的是,在其他一些代码中,我只有一个静态/非成员C函数返回PyObject*
,当从weave
调用时工作得很好。所以我的猜测是在C类对象中使用PyObject*
存在一些问题。但我无法弄清楚是什么。虽然我可以使用上面的代码在PyObject*
界面中创建weave
,但为了便于携带,我宁愿直接由我的班级ngn_rate
提供。
提前感谢您的反馈。
中号
答案 0 :(得分:1)
分段错误的解决方案 - 如注释所示 - 确保初始化Python-C API以及Numpy数组。这可以通过Py_Initialize()
和import_array()
宏来完成,这些宏适当地包含在类ngn_rate
的构造函数中,即,
#include <Python.h>
#include <numpy/arrayobject.h>
class ngn_rate{
...
public:
ngn_rate();
...
};
ngn_rate::ngn_rate{
Py_Initialize();
import_array();
...
}