Reputation: 5363
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
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