0
我在C写了一个漂亮的钳工,我想在python中提供一个接口。所以我为它写了一个扩展模块(见下文)。但是,当我运行时Python扩展模块段错误
from nelder_mead import minimize
minimize(lambda x: x[0]**2, [42])
我得到一个段错误。我不知道从哪里开始调试,这个问题是否明显?当我从C调用钳工时,它工作得很好。
这里是我的包装,功能原始的调配者的顶部:
#include "Python.h"
void _minimize(double (*func)(double* x, void* args), double* x0, int N, void* args);
typedef struct arg_struct {
PyObject* func;
int N;
} arg_struct;
double func(double* x, void* args){
//Build a PyList off of x
int N = ((arg_struct*)args)->N;
PyObject* x_list = PyList_New(N);
for (int i=0; i<N; i++){ PyList_SetItem(x_list, i, PyFloat_FromDouble(x[i])); }
//Pass x_list into the python objective function
PyObject* arglist = Py_BuildValue("(O)", x_list);
PyObject* result = PyObject_CallObject(((arg_struct*)args)->func, arglist);
//Convert result to a double and return
return PyFloat_AsDouble(result);
}
static PyObject* minimize(PyObject* self, PyObject* py_args){
//Get object pointers to f and x0
PyObject* py_func, *x0_list;
if (!PyArg_ParseTuple(py_args, "OO", py_func, x0_list)) return NULL;
//Copy doubles out of x0_list to a regular double* array
int N = PyList_Size(x0_list);
double* x0 = (double*)malloc(N*sizeof(double));
for (int i=0; i<N; i++) x0[i] = PyFloat_AsDouble(PyList_GetItem(x0_list, i));
//Set up an arg_struct and minimize py_func(x0)
arg_struct c_args = { py_func, N };
_minimize(&func, x0, N, (void*)&c_args);
//Now build a list off of x0 and return it
PyObject* result_list = PyList_New(N);
for (int i=0; i<N; i++){ PyList_SetItem(result_list, i, PyFloat_FromDouble(x0[i])); }
return result_list;
}
//Initialize the module with the module table and stuff
static PyMethodDef module_methods[] = {
{ "minimize", minimize, METH_VARARGS, "Minimize a function." },
{ NULL, NULL, 0, NULL }
};
PyMODINIT_FUNC
initnelder_mead(void){
(void) Py_InitModule("nelder_mead", module_methods);
}
这是我的setup.py
:
from distutils.core import setup
from distutils.extension import Extension
setup(name='nelder_mead',
ext_modules = [Extension('nelder_mead', sources = ['wrapper.c', 'nm.c'])])
python文档相当不错,并很好地解释了这一点。你应该仔细阅读文档,_especially_如果你正在用C编写。 –
没有注意到缺少'&')。另外我看了一下cpyton源代码,结果发现PyFloat_AsDouble检查NULL本身并且不能成为段错误的原因,所以我错了。 – robyschek
@robyschek +1对这个比我 –