Dimitri Tcaciuc
Dimitri Tcaciuc

Reputation: 5363

Boost.Python + OpenGL segmentation faults

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) ;
}

Upvotes: 1

Views: 671

Answers (1)

Ulrich von Zadow
Ulrich von Zadow

Reputation: 21

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.

Upvotes: 2

Related Questions