Boost.Python + OpenGL 分段错误

发布于 2024-08-11 17:14:51 字数 2723 浏览 4 评论 0原文

我有一个用 Boost.Python 编写的(几乎)完美运行的 C++ 代码。它包装了一个基于共享指针的 3 或 4 个类的结构层次结构,没有什么非常复杂的(即类 A 有一个类 B 实例指针的 std::vector 等),顶级包称为 foo。

前段时间我决定使用 PyOpenGL 将可视化添加到项目中。所以现在,每当我在 import foo 之前导入 OpenGL 时,我都会在 C++ 代码中遇到分段错误(例如,当我迭代一系列对象及其对象时)子对象。)

我最好的假设是OpenGL以某种方式替代了内存分配函数或者做了一些类似的邪恶的事情。任何人都可以阐明这一情况吗?我会根据要求尝试提供更多详细信息,但整个事情似乎相当混乱。

根据要求,隔离测试用例:

Makefile:

all:
    g++ -shared -o foo.so -fPIC \
        -I/usr/include/boost-1_37/ -I/usr/include/python2.5 \
        -lpython2.5 -lboost_python-1_37 \
        foo.cpp

Python 文件:

from OpenGL import *
import foo

b = foo.B()

for i in range(10):
    b.elements.append(foo.A())

for e in b.elements:
    print e

# Crash here if `from OpenGL import *` is present.

C++ 文件:

#include <boost/python.hpp>
#include <boost/shared_ptr.hpp>
#include <vector>

namespace bp = boost::python;

struct A {
    typedef boost::shared_ptr<A> ptr;
};

struct B {
    typedef boost::shared_ptr<B> ptr;
    std::vector<A::ptr> elements;
};


// Proxies B::elements without converting them 
// back and forth between lists.
struct ElementProxy {

    static ElementProxy 
    init(B::ptr b)
    {
        return ElementProxy(b);
    }

    ElementProxy(B::ptr b)
    : b_(b)
    {}

    size_t
    len() 
    {
        return (*b_).elements.size();
    }

    A::ptr
    getitem(size_t i) 
    {
        if (i >= len()) {
            PyErr_SetString(PyExc_IndexError, "Index out of bounds.");
            bp::throw_error_already_set();
        }
        return (*b_).elements[i];
    }

    void
    append(A::ptr e) 
    {
        (*b_).elements.push_back(e);
    }

    static boost::python::class_<ElementProxy> 
    wrap() 
    {
        return bp::class_<ElementProxy>("ElementProxy", bp::no_init)

            .def("__len__", &ElementProxy::len, 
                 (bp::arg("self")),
                 "Returns the number of contained elements"
                 )

            .def("__getitem__", &ElementProxy::getitem, 
                 (bp::arg("self"), bp::arg("i")), 
                 "Returns the element at given index"
                 )

            .def("append", &ElementProxy::append, 
                 (bp::arg("self"), bp::arg("element")), 
                 "Appends an element"
                 )
            ;
    }

private:

    B::ptr b_;
};



BOOST_PYTHON_MODULE(foo) {

    bp::class_<A, A::ptr, boost::noncopyable>("A") ;

    ElementProxy::wrap();

    bp::class_<B, B::ptr, boost::noncopyable>("B")
        .add_property("elements", &ElementProxy::init) ;
}

I have a (almost) perfectly working C++ code written with Boost.Python. It wraps a shared pointer based structure hierarchy of 3 or 4 classes, nothing terribly complex (i.e. class A has a std::vector of class B instance pointers, etc.), top level package called, say, foo.

Some time ago I decided to add visualization to the project using PyOpenGL. So now, whenever I have import OpenGL before I have import foo, I'm getting segmentation faults inside C++ code (such as when I iterate over a sequence of objects and their child objects.)

My best assumption is that OpenGL somehow substitutes memory allocation functions or does something similarly unholy. Any one can shed some light on the situation? I'll try to provide more details on request, but the whole thing seems to be rather chaotic.

On request, isolated test case:

Makefile:

all:
    g++ -shared -o foo.so -fPIC \
        -I/usr/include/boost-1_37/ -I/usr/include/python2.5 \
        -lpython2.5 -lboost_python-1_37 \
        foo.cpp

Python file:

from OpenGL import *
import foo

b = foo.B()

for i in range(10):
    b.elements.append(foo.A())

for e in b.elements:
    print e

# Crash here if `from OpenGL import *` is present.

C++ file:

#include <boost/python.hpp>
#include <boost/shared_ptr.hpp>
#include <vector>

namespace bp = boost::python;

struct A {
    typedef boost::shared_ptr<A> ptr;
};

struct B {
    typedef boost::shared_ptr<B> ptr;
    std::vector<A::ptr> elements;
};


// Proxies B::elements without converting them 
// back and forth between lists.
struct ElementProxy {

    static ElementProxy 
    init(B::ptr b)
    {
        return ElementProxy(b);
    }

    ElementProxy(B::ptr b)
    : b_(b)
    {}

    size_t
    len() 
    {
        return (*b_).elements.size();
    }

    A::ptr
    getitem(size_t i) 
    {
        if (i >= len()) {
            PyErr_SetString(PyExc_IndexError, "Index out of bounds.");
            bp::throw_error_already_set();
        }
        return (*b_).elements[i];
    }

    void
    append(A::ptr e) 
    {
        (*b_).elements.push_back(e);
    }

    static boost::python::class_<ElementProxy> 
    wrap() 
    {
        return bp::class_<ElementProxy>("ElementProxy", bp::no_init)

            .def("__len__", &ElementProxy::len, 
                 (bp::arg("self")),
                 "Returns the number of contained elements"
                 )

            .def("__getitem__", &ElementProxy::getitem, 
                 (bp::arg("self"), bp::arg("i")), 
                 "Returns the element at given index"
                 )

            .def("append", &ElementProxy::append, 
                 (bp::arg("self"), bp::arg("element")), 
                 "Appends an element"
                 )
            ;
    }

private:

    B::ptr b_;
};



BOOST_PYTHON_MODULE(foo) {

    bp::class_<A, A::ptr, boost::noncopyable>("A") ;

    ElementProxy::wrap();

    bp::class_<B, B::ptr, boost::noncopyable>("B")
        .add_property("elements", &ElementProxy::init) ;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦醒灬来后我 2024-08-18 17:14:52

如果您的操作系统是 Linux,您可能会遇到此错误: https:// /bugs.launchpad.net/ubuntu/+source/mesa/+bug/259219

如果

调用export LD_PRELOAD=

在启动程序之前 可以修复该问题,就是这样。您需要替换为您机器上的实际路径。类似于 /usr/lib/gcc/i686-pc-linux-gnu/4.1.2/libstdc++.so.6。

该错误仅发生在某些图形驱动程序和发行版中,但它相当普遍。特别是,它在 Ubuntu 11.04 中得到了修复。

If your OS is linux, you might be running into this bug: https://bugs.launchpad.net/ubuntu/+source/mesa/+bug/259219.

If calling

export LD_PRELOAD=<path-to-libstdc++>

before starting your program fixes it, this is it. You need to replace with the actual path on your machine. Something like /usr/lib/gcc/i686-pc-linux-gnu/4.1.2/libstdc++.so.6.

The bug only occurs for some graphics drivers and distributions, but it's quite widespread. In particular, it's fixed in Ubuntu 11.04.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文