6#include <boost/core/demangle.hpp>
11namespace boost::python {
12template <
class T,
class A>
struct pointee<xyz::polymorphic<T, A>> {
19namespace bp = boost::python;
24 using X =
typename bp::pointee<Poly>::type;
25 bp::objects::class_value_wrapper<
26 Poly, bp::objects::make_ptr_instance<
27 X, bp::objects::pointer_holder<Poly, X>>>();
71template <
class Base,
class A>
73 : bp::def_visitor<PolymorphicVisitor<xyz::polymorphic<Base, A>>> {
75 static_assert(std::is_polymorphic_v<Base>,
"Type should be polymorphic!");
77 template <
class PyClass>
void visit(PyClass &cl)
const {
78 using T =
typename PyClass::wrapped_type;
79 using meta =
typename PyClass::metadata;
80 using held =
typename meta::held_type;
81 typedef bp::converter::implicit<held, Poly> functions;
84 ALIGATOR_COMPILER_DIAGNOSTIC_IGNORED_DELETE_NON_ABSTRACT_NON_VIRTUAL_DTOR
85 bp::converter::registry::insert(
86 &functions::convertible, &functions::construct, bp::type_id<Poly>(),
87 &bp::converter::expected_from_python_type_direct<T>::get_pytype);
95 if constexpr (std::is_base_of_v<boost::python::wrapper<Base>,
96 typename PyClass::wrapped_type>) {
97 cl.enable_pickling_(
true);
105template <
class... Bases>
107 : bp::def_visitor<PolymorphicMultiBaseVisitor<Bases...>> {
109 template <
class... Args>
void visit(bp::class_<Args...> &cl)
const {
117template <
typename Value>
124 Value *operator()(Value &v) {
return &v; };
125 Value *operator()(Value *v) {
return v; };
128 Value *get_ptr() {
return std::visit(PtrGetter(),
m_held); }
131 template <
typename... Args>
134 std::forward<Args>(args), 0)...)) {
135 boost::python::detail::initialize_wrapper(self, get_ptr());
139 void *holds(boost::python::type_info dst_t,
bool) {
140 if (
void *wrapped = holds_wrapped(dst_t, get_ptr(), get_ptr()))
143 boost::python::type_info src_t = boost::python::type_id<Value>();
144 return src_t == dst_t ? get_ptr()
146 get_ptr(), src_t, dst_t);
150 inline void *holds_wrapped(boost::python::type_info dst_t,
151 boost::python::wrapper<T> *, T *p) {
152 return boost::python::type_id<T>() == dst_t ? p : 0;
155 inline void *holds_wrapped(boost::python::type_info, ...) {
return 0; }
185template <
typename _PyBase,
typename _Base>
192 : bp::wrapper<
Base>(o) {
201 bp::wrapper<Base>::operator=(o);
208 void deepcopy_owner() {
209 namespace bp = boost::python;
210 if (PyObject *owner_ptr = bp::detail::wrapper_base_::get_owner(*
this)) {
211 bp::object copy = bp::import(
"copy");
212 bp::object deepcopy = copy.attr(
"deepcopy");
217 bp::object owner{bp::handle<>(bp::borrowed(owner_ptr))};
223 copied_owner = deepcopy(owner);
224 PyObject *copied_owner_ptr = copied_owner.ptr();
233 bp::objects::instance<> *inst =
234 ((bp::objects::instance<> *)copied_owner_ptr);
238 std::ostringstream error_msg;
239 error_msg <<
"OwningNonOwningHolder should be setup for "
240 << boost::core::demangle(
typeid(
PyBase).name()) <<
" type"
242 throw std::logic_error(error_msg.str());
246 bp::detail::initialize_wrapper(copied_owner_ptr,
this);
251 bp::object copied_owner;
261template <
class poly_ref,
class MakeHolder>
struct ToPythonIndirectPoly {
262 using poly_type = boost::remove_cv_ref_t<poly_ref>;
264 template <
class U> PyObject *operator()(U
const &x)
const {
265 return execute(
const_cast<U &
>(x));
267#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
268 PyTypeObject
const *get_pytype() {
269 return boost::python::converter::registered_pytype<poly_type>::get_pytype();
274 template <
class T,
class A>
275 static PyObject *execute(
const xyz::polymorphic<T, A> &p) {
277 return bp::detail::none();
280 return bp::to_python_indirect<const T &, MakeHolder>{}(q);
291template <
class T,
class A,
class MakeHolder>
292struct to_python_indirect<xyz::polymorphic<T, A> &, MakeHolder>
293 : aligator::python::internal::ToPythonIndirectPoly<xyz::polymorphic<T, A> &,
296template <
class T,
class A,
class MakeHolder>
297struct to_python_indirect<const xyz::polymorphic<T, A> &, MakeHolder>
298 : aligator::python::internal::ToPythonIndirectPoly<
299 const xyz::polymorphic<T, A> &, MakeHolder> {};
bool valueless_after_move() const noexcept
#define ALIGATOR_COMPILER_DIAGNOSTIC_PUSH
macros for pragma push/pop/ignore deprecated warnings
#define ALIGATOR_COMPILER_DIAGNOSTIC_POP
void register_polymorphic_to_python()
Expose a polymorphic value type, e.g. xyz::polymorphic<T, A>.
T * get_pointer(::xyz::polymorphic< T, A > const &x)
std::variant< Value, Value * > m_held
OwningNonOwningHolder(PyObject *self, Args... args)
void visit(bp::class_< Args... > &cl) const
xyz::polymorphic< Base, A > Poly
void visit(PyClass &cl) const
PolymorphicWrapper & operator=(PolymorphicWrapper &&o)=default
PolymorphicWrapper(const PolymorphicWrapper &o)
PolymorphicWrapper & operator=(const PolymorphicWrapper &o)
PolymorphicWrapper(PolymorphicWrapper &&o)=default
PolymorphicWrapper()=default