Boost + Python + Numpy = SIGSEGV

时间:2016-11-16 14:34:16

标签: python python-3.x numpy boost boost-python

我目前正在开始使用Python(版本3.5)。对于当前项目,我想通过使用Boost-Python为此函数编写包装器来包含一些C代码(用于模拟)。由于这个模拟器的结果将用于NumPy的计算,我想在C-Code中支持NumPy Arrays。

我编写的包装器实际上工作正常,但是当脚本执行后终止Python解释器时,有时会发生SIGSEGV。我试着研究Boost-Python如何处理内存所有权,但我找不到有用的信息来源。

因此,我想问一下是否有人知道为什么这些SIGSEGV会继续发生。该问题的相关代码如下:

setup.py(我正在使用python setup.py install构建项目)

from setuptools import setup, Extension
import os
import sys

source_path = os.path.dirname(os.path.realpath(sys.argv[0]))
dummy = Extension('dummypackage.dummy',
                  [os.path.join(source_path, "dummy.cpp")],
                  include_dirs=[source_path],
                  library_dirs=['/'],
                  libraries=['boost_python'],
                  extra_compile_args=['-g', '-Wno-return-type'])

setup(
    name="Dummy Project",
    version="1.0",
    install_requirements=[
        "numpy",
    ],
    ext_modules=[dummy],
)

dummy.cpp

#include "dummy.h"

#include "math.h"
#define SQ(x) ((x)*(x))

namespace mlpmp {

    using namespace boost::python;

    // Helper function for ND Array conversion
    object to_ndarray(double* data, int nd, npy_intp* size){
        PyObject *object = PyArray_SimpleNewFromData(nd, size, NPY_DOUBLE, data);
        handle<> handle(object);
        numeric::array array(handle);

        return array.copy();
    }

    dict Foo::func(dict val){

        //Extract the arguments from the python dictionaries    
        numeric::array a = extract<numeric::array>(val["a"]);
        numeric::array b = extract<numeric::array>(val["b"]);

        double out_val[2];
        //... do some computations with the arrays and store them in out_val

        npy_intp size = 2;

        dict res;
        res["a"] = a.copy();
        res["b"] = b.copy();
        res["res"] = to_ndarray(out_val, 1, &size);

        return res;
    }
}

dummy.h

#define PY_ARRAY_UNIQUE_SYMBOL dummy
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include <numpy/arrayobject.h>

#include <boost/python.hpp>

void* init_numpy(){
    import_array()
}

namespace mlpmp {

    using namespace boost::python;

    class Foo {
        public:
            static dict func(dict val);
    };

    BOOST_PYTHON_MODULE(dummy){
        init_numpy();
        numeric::array::set_module_and_type("numpy", "ndarray");

        class_<Foo>("Foo")
            .def("func", &Foo::func)
            .staticmethod("func");
    }

}

有趣的是,仅使用“extract”函数访问“val”字典以引起SIGSEGV也足够了。我通过返回一个空数组但仍然访问数据来检查这个。如果我返回一个空数组而不访问“val”字典,一切正常。

最后要提到的一点是,SIGSEGV并不是每次运行都会发生,而是(在我的情况下)每隔三到四次 - 所以如果你想验证问题,你需要重复几次。

如果有人可以帮助我,那就太棒了

最佳, 帕斯卡

0 个答案:

没有答案