Segfault от передачи общего указателя между объектами C ++ через Boost Python - PullRequest
0 голосов
/ 06 мая 2018

У меня есть два пользовательских класса C ++ Foo и Baz, которые я успешно представил Python через Boost Python; пользователь взаимодействует с классами Python, которые запускают свои аналоги C ++ под капотом. Важным вариантом использования является передача Foo экземпляра Python методу Python Baz.run_that_foo. Метод привязки Python:

// 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>`
}

Важно, что ps_ptr должен быть общим указателем на экземпляр PlanningScene (т.е. std::shared_ptr<planning_scene::PlanningScene>), где этот класс объявлен как

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

В моем классе C ++ Foo,

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

где ps_ - действительный общий указатель на экземпляр PlanningScene, созданный с помощью std::make_shared в конструкторе Foo.

Выполнение некоторых интеграционных тестов C ++ работает нормально, где я передаю foo_ptr непосредственно в C ++ с Foo до Baz. Но интеграционные тесты Python (которые используют класс привязок) не проходят на Segmentation fault (core dumped). Что здесь может быть не так? Я разобрался со многими SO вопросами о проблемах с Boost Python, enable_shared_from_this и т. Д., Но безрезультатно. Заранее спасибо!

1 Ответ

0 голосов
/ 08 мая 2018

Хитрость заключается в том, чтобы использовать boost::bind для создания оболочки перенаправления вызовов вокруг метода, который мы вызываем из класса привязок Python (т.е. FooPython.GetPSPtr):

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