У меня есть два пользовательских класса 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 segfaults, enable_shared_from_this и т. д., Но безрезультатно. Заранее спасибо!
Хороший звонок @JiveDadson: согласно эта проблема Boost Python, похоже, что Boost Python не поддерживает C++ 11 std :: shared_ptr до v1.63.0. К сожалению, std::enable_shared_from_this требует использования общего указателя std::, а не boost::, и я застрял на boost v1.58.0 для совместимости с другими пакетами в моем проекте.
Использовать shared_ptr :: get () для передачи необработанного указателя на Python?
А что насчет паттерна PIMPL? Поместите общий ptr в структуру и добавьте несколько методов пересылки.
Хорошее предложение @ DanMašek, я не был знаком с Шаблон PImpl. Вкратце, решение, которое я только что опубликовал, делает это с boost::bind.





Уловка состоит в том, чтобы использовать 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)());
}
Вы уверены, что для интерфейса Python требуется shared_ptr, а не необработанный указатель?