BoltzmannBrain
BoltzmannBrain

Reputation: 5392

Segfault from passing a shared pointer between C++ objects via Boost Python

I have two custom C++ classes Foo and Baz that I've successfully exposed to Python via Boost Python; the user interacts with Python classes that run their C++ counterparts under the hood. An important use case is passing a Foo Python instance to a Python method Baz.run_that_foo. The Python bindings method is,

// Note `XPython` is the name for the Boost Python bindings class of `X`.

void BazPython::RunThatFoo(const bp::object & foo) {
    FooPython & foo_obj = bp::extract<FooPython&>(foo);
    auto ps_ptr = foo_obj.GetPSPtr();
    Baz::DoPSComputation(ps_ptr);  // Expects a `const std::shared_ptr<planning_scene::PlanningScene>`
}

Importantly, ps_ptr is supposed to be a shared pointer to a PlanningScene instance (i.e., std::shared_ptr<planning_scene::PlanningScene>), where that class is declared as,

class PlanningScene : private boost::noncopyable, public std::enable_shared_from_this<PlanningScene>

In the C++ Foo class I have,

std::shared_ptr<planning_scene::PlanningScene> Foo::GetPSPtr() {  // two different attempts shown
    // return ps_;
    return (*ps_).shared_from_this();
}

where ps_ is a valid shared pointer to a PlanningScene instance created via std::make_shared in the Foo constructor.

Running some C++ integration tests works fine, where I pass a foo_ptr directly in C++ from Foo to Baz. But python integration tests (that use the bindings class) fail on Segmentation fault (core dumped). What could be wrong here? I've dug around many SO questions on Boost Python segfaults, enable_shared_from_this, etc., but to no avail. Thanks in advance!

Upvotes: 1

Views: 334

Answers (1)

BoltzmannBrain
BoltzmannBrain

Reputation: 5392

The trick is to use boost::bind to generate a forwarding call wrapper around the method we're invoking from a Python-bindings class (i.e. FooPython.GetPSPtr):

void BazPython::RunThatFoo(const bp::object & foo) {
    FooPython & foo_obj = bp::extract<FooPython&>(foo);
    Baz::DoPSComputation(boost::bind(&Foo::GetPSPtr, &foo_obj)());
}

Upvotes: 1

Related Questions