Я создаю свой собственный модуль python на C++. Исходный код модуля:Ошибка ошибки случайного сегментации в модуле python C++
#include <Python.h>
#include <numpy/arrayobject.h>
#include "FMM.h"
struct module_state {
PyObject *error;
};
#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
static PyObject* FMM(PyObject* self, PyObject* args)
{
PyObject *model_obj;
PyObject *time_obj;
PyObject *accepted_obj;
PyObject *lat_obj;
PyObject *lon_obj;
PyObject *h_obj;
int N;
if (!PyArg_ParseTuple(args, "OOOOOOi", &model_obj, &time_obj, &accepted_obj, &lat_obj, &lon_obj, &h_obj, &N))
{
Py_INCREF(Py_None);
return Py_None;
}
PyObject *model = PyArray_FROM_OTF(model_obj, NPY_FLOAT, NPY_INOUT_ARRAY);
PyObject *time = PyArray_FROM_OTF(time_obj, NPY_FLOAT, NPY_INOUT_ARRAY);
PyObject *accepted = PyArray_FROM_OTF(accepted_obj, NPY_BOOL, NPY_INOUT_ARRAY);
PyObject *lat = PyArray_FROM_OTF(lon_obj, NPY_DOUBLE, NPY_INOUT_ARRAY);
PyObject *lon = PyArray_FROM_OTF(lon_obj, NPY_DOUBLE, NPY_INOUT_ARRAY);
PyObject *h = PyArray_FROM_OTF(h_obj, NPY_DOUBLE, NPY_INOUT_ARRAY);
float *MODEL = static_cast<float *>(PyArray_DATA(model_obj));
float *TIME = static_cast<float *>(PyArray_DATA(time_obj));
bool *ACCEPTED = static_cast<bool *>(PyArray_DATA(accepted_obj));
double *LAT = static_cast<double *>(PyArray_DATA(lat_obj));
double *LON = static_cast<double *>(PyArray_DATA(lon_obj));
double *H = static_cast<double *>(PyArray_DATA(h_obj));
_FMM(MODEL, TIME, ACCEPTED, LAT, LON, H, N);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject* SetModelSize(PyObject* self, PyObject* args)
{
int x, y, z;
if (!PyArg_ParseTuple(args, "iii", &x, &y, &z))
{
Py_INCREF(Py_None);
return Py_None;
}
_SaveModelSize(x, y, z);
// Rerutn values
Py_INCREF(Py_None);
return Py_None;
}
static PyMethodDef FMMMethods[] = {
{"FMM", FMM, METH_VARARGS, "Some Text"},
{"SetModelSize", SetModelSize, METH_VARARGS, "Some Text"},
{NULL, NULL, 0, NULL}
};
static int FMM_traverse(PyObject *m, visitproc visit, void *arg) {
Py_VISIT(GETSTATE(m)->error);
return 0;
}
static int FMM_clear(PyObject *m) {
Py_CLEAR(GETSTATE(m)->error);
return 0;
}
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"FMM",
NULL,
sizeof(struct module_state),
FMMMethods,
NULL,
FMM_traverse,
FMM_clear,
NULL
};
extern "C" PyObject * PyInit_FMM(void)
{
PyObject *module = PyModule_Create(&moduledef);
if (module == NULL)
return NULL;
struct module_state *st = GETSTATE(module);
st->error = PyErr_NewException("FMM.Error", NULL, NULL);
if (st->error == NULL)
{
Py_DECREF(module);
return NULL;
}
import_array();
Py_INCREF(module);
return module;
}
Моя функция _FMM делает численные расчеты на больших наборах данных (два floats
и bool
имеет размер 2E9 элементов
модуль компилируется с помощью setup.py:.
from distutils.core import setup, Extension
import numpy.distutils.misc_util
import os
os.environ["CC"] = "g++"
os.environ["CXX"] = "g++"
module1 = Extension('FMM', sources = ['FMMmodule.c', 'FMM.c'])
setup (name = 'PackageName',
version = '1.0',
description = 'This is a demo package',
ext_modules = [module1],
include_dirs=numpy.distutils.misc_util.get_numpy_include_dirs())
Когда я запускаю его из python, я получаю ошибку сегментации после примерно 60 секунд вычисления.
Каждый раз, когда я запускаю на разных этапах расчета. Я читал, что это может быть связано с неправильным использованием Py_INCREF()
и Py_DECREF()
- попытался сыграть с этим без везения.
У кого-нибудь есть опыт работы с таким поведением?
Я тестирую с использованием python 3.4.
Вызов функции 'FMM' просто вызывает проблемы, так как название предполагает, что это макрос. Тем не менее, все эти стили C-стиля будут только замалчивать важные предупреждения компилятора, вместо этого использовать C++-приведения, если они действительно необходимы, и затем отчитываться, если вы нашли свою проблему. –
Изменение кастинга на стиль C++ ничего не изменило. – gozwei
Ну, по крайней мере, вы могли бы здесь обновить код. –