2016-01-02 2 views
0

Я создаю свой собственный модуль 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.

+1

Вызов функции 'FMM' просто вызывает проблемы, так как название предполагает, что это макрос. Тем не менее, все эти стили C-стиля будут только замалчивать важные предупреждения компилятора, вместо этого использовать C++-приведения, если они действительно необходимы, и затем отчитываться, если вы нашли свою проблему. –

+0

Изменение кастинга на стиль C++ ничего не изменило. – gozwei

+1

Ну, по крайней мере, вы могли бы здесь обновить код. –

ответ

0

Я, наконец, разобрал это. Мне пришлось изменить код, чтобы сделать его совместимым с новым numpy c-api: см. Здесь: Migrating to numpy api 1.7

Смежные вопросы