Чисто виртуальный базовый класс boost::python со статическим конструктором фабрики и std::unique_ptr
Я посмотрел на все связанные вопросы, которые смог найти, и не смог найти ответ на эту конкретную ситуацию.
У меня есть чистый виртуальный интерфейс базового класса C++, который я хочу представить в Python. Реализация наследуется от Base и не раскрывается:
struct Base : private boost::noncopyable
{
static std::unique_ptr<Base> create();
virtual ~Base();
virtual int get_int() = 0;
virtual void set_int(const int i) = 0;
};
Мне не нужен Python для создания подкласса Base, только чтобы иметь возможность создавать новые экземпляры Base через create()
заводская функция.
Я пробовал два подхода к упаковке с помощью Boost:: Python. Во-первых, похоже на Boost.Python: как выставить std::unique_ptr Я пытался создать __init__
функция, которая выпускает unique_ptr:
namespace bp = boost::python;
bp::class_<Base, boost::noncopyable>("Base", bp::no_init)
.def("__init__",
bp::make_function([](Base& self) { return Master::create().release(); },
bp::return_value_policy<bp::manage_new_object>(),
boost::mpl::vector<Base*, Base&>(), "Create a new Base")
.staticmethod("__init__")
Это компилируется и загружается в Python, но __init__
на самом деле не статично!
create(...)
create( (Base)arg1) -> Base :
Create a new Base
C++ signature :
Base* create(Base {lvalue})
Второй подход, который я попробовал, заключается в использовании make_constructor
следующее:
namespace bp = boost::python;
bp::class_<Base, boost::noncopyable, std::unique_ptr<Base>>("Base", bp::no_init)
.def("__init__", bp::make_constructor(&Base::create));
bp::register_ptr_to_python<std::unique_ptr<Master>>();
Однако это не компилируется: /usr/include/boost/python/make_constructor.hpp:40:20: fatal error: call to deleted constructor of std::unique_ptr<Base, std::default_delete<Base>> dispatch(x, is_pointer<T>());
1 ответ
Мне удалось заставить привязки работать, используя второй подход, переключившись с std::unique_ptr на std::shared_ptr, так как shared_ptr является конструируемым по умолчанию.
Это стало возможным, потому что я могу изменить исходный код библиотеки C++.