gpt4 book ai didi

python - C++ 类成员函数返回 PyObject* 段错误

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:18:37 24 4
gpt4 key购买 nike

在一些生物物理模型的模拟框架内,我有一个 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 接口(interface)。所以调用 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

不幸的是,当我运行上述模块时,它会产生段错误。经过一些调试和试错后,我发现问题是由 ng_networks.h 中的 PyObject* out_array 初始化引起的。事实上,当我在 weave 的 C 代码中创建 PyObject* 时,它完美地工作:也就是说,我修改了 ngn_rate::bifsystem() 类成员函数,以便它返回 double*,然后我在 weave 接口(interface)中从后者构建 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* 存在一些问题。但我不知道是什么。尽管我可以使用上面的代码在 weave 界面中创建 PyObject*,但为了可移植性,我宁愿让我的类 ngn_rate< 直接提供它.

提前感谢您的反馈。

中号

最佳答案

段错误的解决方案是——正如评论所建议的——确保初始化 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();

...
}

关于python - C++ 类成员函数返回 PyObject* 段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29851529/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com