1

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!

5
  • Are you sure that the Python interface requires a shared_ptr and not a raw pointer? Commented May 6, 2018 at 17:01
  • Good call @JiveDadson: According to this Boost Python issue, it looks like Boost Python doesn't support C++ 11 std::shared_ptr, until v1.63.0. Unfortunately the std::enable_shared_from_this necessitates the use of std:: rather than boost:: shared pointer, and I'm stuck with boost v1.58.0 for compatibility w/ other packages in my project. Commented May 6, 2018 at 18:06
  • Use shared_ptr::get() to pass a raw pointer to Python? Commented May 6, 2018 at 18:21
  • What about something like a PIMPL pattern? Put the shared ptr into a struct, and add some forwarding methods. Commented May 7, 2018 at 13:58
  • 1
    Good suggestion @DanMašek, I was not familiar with the PImpl pattern. In a hand-wavy way, the solution I just posted does this w/ boost::bind. Commented May 8, 2018 at 2:32

1 Answer 1

1

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)());
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.