File indexing completed on 2025-02-23 05:15:01
0001 /* 0002 pybind11/detail/init.h: init factory function implementation and support code. 0003 0004 Copyright (c) 2017 Jason Rhinelander <jason@imaginary.ca> 0005 0006 All rights reserved. Use of this source code is governed by a 0007 BSD-style license that can be found in the LICENSE file. 0008 */ 0009 0010 #pragma once 0011 0012 #include "class.h" 0013 0014 PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) 0015 PYBIND11_NAMESPACE_BEGIN(detail) 0016 0017 template <> 0018 class type_caster<value_and_holder> { 0019 public: 0020 bool load(handle h, bool) { 0021 value = reinterpret_cast<value_and_holder *>(h.ptr()); 0022 return true; 0023 } 0024 0025 template <typename> using cast_op_type = value_and_holder &; 0026 explicit operator value_and_holder &() { return *value; } 0027 static constexpr auto name = const_name<value_and_holder>(); 0028 0029 private: 0030 value_and_holder *value = nullptr; 0031 }; 0032 0033 PYBIND11_NAMESPACE_BEGIN(initimpl) 0034 0035 inline void no_nullptr(void *ptr) { 0036 if (!ptr) throw type_error("pybind11::init(): factory function returned nullptr"); 0037 } 0038 0039 // Implementing functions for all forms of py::init<...> and py::init(...) 0040 template <typename Class> using Cpp = typename Class::type; 0041 template <typename Class> using Alias = typename Class::type_alias; 0042 template <typename Class> using Holder = typename Class::holder_type; 0043 0044 template <typename Class> using is_alias_constructible = std::is_constructible<Alias<Class>, Cpp<Class> &&>; 0045 0046 // Takes a Cpp pointer and returns true if it actually is a polymorphic Alias instance. 0047 template <typename Class, enable_if_t<Class::has_alias, int> = 0> 0048 bool is_alias(Cpp<Class> *ptr) { 0049 return dynamic_cast<Alias<Class> *>(ptr) != nullptr; 0050 } 0051 // Failing fallback version of the above for a no-alias class (always returns false) 0052 template <typename /*Class*/> 0053 constexpr bool is_alias(void *) { return false; } 0054 0055 // Constructs and returns a new object; if the given arguments don't map to a constructor, we fall 0056 // back to brace aggregate initiailization so that for aggregate initialization can be used with 0057 // py::init, e.g. `py::init<int, int>` to initialize a `struct T { int a; int b; }`. For 0058 // non-aggregate types, we need to use an ordinary T(...) constructor (invoking as `T{...}` usually 0059 // works, but will not do the expected thing when `T` has an `initializer_list<T>` constructor). 0060 template <typename Class, typename... Args, detail::enable_if_t<std::is_constructible<Class, Args...>::value, int> = 0> 0061 inline Class *construct_or_initialize(Args &&...args) { return new Class(std::forward<Args>(args)...); } 0062 template <typename Class, typename... Args, detail::enable_if_t<!std::is_constructible<Class, Args...>::value, int> = 0> 0063 inline Class *construct_or_initialize(Args &&...args) { return new Class{std::forward<Args>(args)...}; } 0064 0065 // Attempts to constructs an alias using a `Alias(Cpp &&)` constructor. This allows types with 0066 // an alias to provide only a single Cpp factory function as long as the Alias can be 0067 // constructed from an rvalue reference of the base Cpp type. This means that Alias classes 0068 // can, when appropriate, simply define a `Alias(Cpp &&)` constructor rather than needing to 0069 // inherit all the base class constructors. 0070 template <typename Class> 0071 void construct_alias_from_cpp(std::true_type /*is_alias_constructible*/, 0072 value_and_holder &v_h, Cpp<Class> &&base) { 0073 v_h.value_ptr() = new Alias<Class>(std::move(base)); 0074 } 0075 template <typename Class> 0076 [[noreturn]] void construct_alias_from_cpp(std::false_type /*!is_alias_constructible*/, 0077 value_and_holder &, Cpp<Class> &&) { 0078 throw type_error("pybind11::init(): unable to convert returned instance to required " 0079 "alias class: no `Alias<Class>(Class &&)` constructor available"); 0080 } 0081 0082 // Error-generating fallback for factories that don't match one of the below construction 0083 // mechanisms. 0084 template <typename Class> 0085 void construct(...) { 0086 static_assert(!std::is_same<Class, Class>::value /* always false */, 0087 "pybind11::init(): init function must return a compatible pointer, " 0088 "holder, or value"); 0089 } 0090 0091 // Pointer return v1: the factory function returns a class pointer for a registered class. 0092 // If we don't need an alias (because this class doesn't have one, or because the final type is 0093 // inherited on the Python side) we can simply take over ownership. Otherwise we need to try to 0094 // construct an Alias from the returned base instance. 0095 template <typename Class> 0096 void construct(value_and_holder &v_h, Cpp<Class> *ptr, bool need_alias) { 0097 PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(need_alias); 0098 no_nullptr(ptr); 0099 if (PYBIND11_SILENCE_MSVC_C4127(Class::has_alias) && need_alias && !is_alias<Class>(ptr)) { 0100 // We're going to try to construct an alias by moving the cpp type. Whether or not 0101 // that succeeds, we still need to destroy the original cpp pointer (either the 0102 // moved away leftover, if the alias construction works, or the value itself if we 0103 // throw an error), but we can't just call `delete ptr`: it might have a special 0104 // deleter, or might be shared_from_this. So we construct a holder around it as if 0105 // it was a normal instance, then steal the holder away into a local variable; thus 0106 // the holder and destruction happens when we leave the C++ scope, and the holder 0107 // class gets to handle the destruction however it likes. 0108 v_h.value_ptr() = ptr; 0109 v_h.set_instance_registered(true); // To prevent init_instance from registering it 0110 v_h.type->init_instance(v_h.inst, nullptr); // Set up the holder 0111 Holder<Class> temp_holder(std::move(v_h.holder<Holder<Class>>())); // Steal the holder 0112 v_h.type->dealloc(v_h); // Destroys the moved-out holder remains, resets value ptr to null 0113 v_h.set_instance_registered(false); 0114 0115 construct_alias_from_cpp<Class>(is_alias_constructible<Class>{}, v_h, std::move(*ptr)); 0116 } else { 0117 // Otherwise the type isn't inherited, so we don't need an Alias 0118 v_h.value_ptr() = ptr; 0119 } 0120 } 0121 0122 // Pointer return v2: a factory that always returns an alias instance ptr. We simply take over 0123 // ownership of the pointer. 0124 template <typename Class, enable_if_t<Class::has_alias, int> = 0> 0125 void construct(value_and_holder &v_h, Alias<Class> *alias_ptr, bool) { 0126 no_nullptr(alias_ptr); 0127 v_h.value_ptr() = static_cast<Cpp<Class> *>(alias_ptr); 0128 } 0129 0130 // Holder return: copy its pointer, and move or copy the returned holder into the new instance's 0131 // holder. This also handles types like std::shared_ptr<T> and std::unique_ptr<T> where T is a 0132 // derived type (through those holder's implicit conversion from derived class holder constructors). 0133 template <typename Class> 0134 void construct(value_and_holder &v_h, Holder<Class> holder, bool need_alias) { 0135 PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(need_alias); 0136 auto *ptr = holder_helper<Holder<Class>>::get(holder); 0137 no_nullptr(ptr); 0138 // If we need an alias, check that the held pointer is actually an alias instance 0139 if (PYBIND11_SILENCE_MSVC_C4127(Class::has_alias) && need_alias && !is_alias<Class>(ptr)) 0140 throw type_error("pybind11::init(): construction failed: returned holder-wrapped instance " 0141 "is not an alias instance"); 0142 0143 v_h.value_ptr() = ptr; 0144 v_h.type->init_instance(v_h.inst, &holder); 0145 } 0146 0147 // return-by-value version 1: returning a cpp class by value. If the class has an alias and an 0148 // alias is required the alias must have an `Alias(Cpp &&)` constructor so that we can construct 0149 // the alias from the base when needed (i.e. because of Python-side inheritance). When we don't 0150 // need it, we simply move-construct the cpp value into a new instance. 0151 template <typename Class> 0152 void construct(value_and_holder &v_h, Cpp<Class> &&result, bool need_alias) { 0153 PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(need_alias); 0154 static_assert(std::is_move_constructible<Cpp<Class>>::value, 0155 "pybind11::init() return-by-value factory function requires a movable class"); 0156 if (PYBIND11_SILENCE_MSVC_C4127(Class::has_alias) && need_alias) 0157 construct_alias_from_cpp<Class>(is_alias_constructible<Class>{}, v_h, std::move(result)); 0158 else 0159 v_h.value_ptr() = new Cpp<Class>(std::move(result)); 0160 } 0161 0162 // return-by-value version 2: returning a value of the alias type itself. We move-construct an 0163 // Alias instance (even if no the python-side inheritance is involved). The is intended for 0164 // cases where Alias initialization is always desired. 0165 template <typename Class> 0166 void construct(value_and_holder &v_h, Alias<Class> &&result, bool) { 0167 static_assert(std::is_move_constructible<Alias<Class>>::value, 0168 "pybind11::init() return-by-alias-value factory function requires a movable alias class"); 0169 v_h.value_ptr() = new Alias<Class>(std::move(result)); 0170 } 0171 0172 // Implementing class for py::init<...>() 0173 template <typename... Args> 0174 struct constructor { 0175 template <typename Class, typename... Extra, enable_if_t<!Class::has_alias, int> = 0> 0176 static void execute(Class &cl, const Extra&... extra) { 0177 cl.def("__init__", [](value_and_holder &v_h, Args... args) { 0178 v_h.value_ptr() = construct_or_initialize<Cpp<Class>>(std::forward<Args>(args)...); 0179 }, is_new_style_constructor(), extra...); 0180 } 0181 0182 template <typename Class, typename... Extra, 0183 enable_if_t<Class::has_alias && 0184 std::is_constructible<Cpp<Class>, Args...>::value, int> = 0> 0185 static void execute(Class &cl, const Extra&... extra) { 0186 cl.def("__init__", [](value_and_holder &v_h, Args... args) { 0187 if (Py_TYPE(v_h.inst) == v_h.type->type) 0188 v_h.value_ptr() = construct_or_initialize<Cpp<Class>>(std::forward<Args>(args)...); 0189 else 0190 v_h.value_ptr() = construct_or_initialize<Alias<Class>>(std::forward<Args>(args)...); 0191 }, is_new_style_constructor(), extra...); 0192 } 0193 0194 template <typename Class, typename... Extra, 0195 enable_if_t<Class::has_alias && 0196 !std::is_constructible<Cpp<Class>, Args...>::value, int> = 0> 0197 static void execute(Class &cl, const Extra&... extra) { 0198 cl.def("__init__", [](value_and_holder &v_h, Args... args) { 0199 v_h.value_ptr() = construct_or_initialize<Alias<Class>>(std::forward<Args>(args)...); 0200 }, is_new_style_constructor(), extra...); 0201 } 0202 }; 0203 0204 // Implementing class for py::init_alias<...>() 0205 template <typename... Args> struct alias_constructor { 0206 template <typename Class, typename... Extra, 0207 enable_if_t<Class::has_alias && std::is_constructible<Alias<Class>, Args...>::value, int> = 0> 0208 static void execute(Class &cl, const Extra&... extra) { 0209 cl.def("__init__", [](value_and_holder &v_h, Args... args) { 0210 v_h.value_ptr() = construct_or_initialize<Alias<Class>>(std::forward<Args>(args)...); 0211 }, is_new_style_constructor(), extra...); 0212 } 0213 }; 0214 0215 // Implementation class for py::init(Func) and py::init(Func, AliasFunc) 0216 template <typename CFunc, typename AFunc = void_type (*)(), 0217 typename = function_signature_t<CFunc>, typename = function_signature_t<AFunc>> 0218 struct factory; 0219 0220 // Specialization for py::init(Func) 0221 template <typename Func, typename Return, typename... Args> 0222 struct factory<Func, void_type (*)(), Return(Args...)> { 0223 remove_reference_t<Func> class_factory; 0224 0225 // NOLINTNEXTLINE(google-explicit-constructor) 0226 factory(Func &&f) : class_factory(std::forward<Func>(f)) {} 0227 0228 // The given class either has no alias or has no separate alias factory; 0229 // this always constructs the class itself. If the class is registered with an alias 0230 // type and an alias instance is needed (i.e. because the final type is a Python class 0231 // inheriting from the C++ type) the returned value needs to either already be an alias 0232 // instance, or the alias needs to be constructible from a `Class &&` argument. 0233 template <typename Class, typename... Extra> 0234 void execute(Class &cl, const Extra &...extra) && { 0235 #if defined(PYBIND11_CPP14) 0236 cl.def("__init__", [func = std::move(class_factory)] 0237 #else 0238 auto &func = class_factory; 0239 cl.def("__init__", [func] 0240 #endif 0241 (value_and_holder &v_h, Args... args) { 0242 construct<Class>(v_h, func(std::forward<Args>(args)...), 0243 Py_TYPE(v_h.inst) != v_h.type->type); 0244 }, is_new_style_constructor(), extra...); 0245 } 0246 }; 0247 0248 // Specialization for py::init(Func, AliasFunc) 0249 template <typename CFunc, typename AFunc, 0250 typename CReturn, typename... CArgs, typename AReturn, typename... AArgs> 0251 struct factory<CFunc, AFunc, CReturn(CArgs...), AReturn(AArgs...)> { 0252 static_assert(sizeof...(CArgs) == sizeof...(AArgs), 0253 "pybind11::init(class_factory, alias_factory): class and alias factories " 0254 "must have identical argument signatures"); 0255 static_assert(all_of<std::is_same<CArgs, AArgs>...>::value, 0256 "pybind11::init(class_factory, alias_factory): class and alias factories " 0257 "must have identical argument signatures"); 0258 0259 remove_reference_t<CFunc> class_factory; 0260 remove_reference_t<AFunc> alias_factory; 0261 0262 factory(CFunc &&c, AFunc &&a) 0263 : class_factory(std::forward<CFunc>(c)), alias_factory(std::forward<AFunc>(a)) { } 0264 0265 // The class factory is called when the `self` type passed to `__init__` is the direct 0266 // class (i.e. not inherited), the alias factory when `self` is a Python-side subtype. 0267 template <typename Class, typename... Extra> 0268 void execute(Class &cl, const Extra&... extra) && { 0269 static_assert(Class::has_alias, "The two-argument version of `py::init()` can " 0270 "only be used if the class has an alias"); 0271 #if defined(PYBIND11_CPP14) 0272 cl.def("__init__", [class_func = std::move(class_factory), alias_func = std::move(alias_factory)] 0273 #else 0274 auto &class_func = class_factory; 0275 auto &alias_func = alias_factory; 0276 cl.def("__init__", [class_func, alias_func] 0277 #endif 0278 (value_and_holder &v_h, CArgs... args) { 0279 if (Py_TYPE(v_h.inst) == v_h.type->type) 0280 // If the instance type equals the registered type we don't have inheritance, so 0281 // don't need the alias and can construct using the class function: 0282 construct<Class>(v_h, class_func(std::forward<CArgs>(args)...), false); 0283 else 0284 construct<Class>(v_h, alias_func(std::forward<CArgs>(args)...), true); 0285 }, is_new_style_constructor(), extra...); 0286 } 0287 }; 0288 0289 /// Set just the C++ state. Same as `__init__`. 0290 template <typename Class, typename T> 0291 void setstate(value_and_holder &v_h, T &&result, bool need_alias) { 0292 construct<Class>(v_h, std::forward<T>(result), need_alias); 0293 } 0294 0295 /// Set both the C++ and Python states 0296 template <typename Class, typename T, typename O, 0297 enable_if_t<std::is_convertible<O, handle>::value, int> = 0> 0298 void setstate(value_and_holder &v_h, std::pair<T, O> &&result, bool need_alias) { 0299 construct<Class>(v_h, std::move(result.first), need_alias); 0300 auto d = handle(result.second); 0301 if (PyDict_Check(d.ptr()) && PyDict_Size(d.ptr()) == 0) { 0302 // Skipping setattr below, to not force use of py::dynamic_attr() for Class unnecessarily. 0303 // See PR #2972 for details. 0304 return; 0305 } 0306 setattr((PyObject *) v_h.inst, "__dict__", d); 0307 } 0308 0309 /// Implementation for py::pickle(GetState, SetState) 0310 template <typename Get, typename Set, 0311 typename = function_signature_t<Get>, typename = function_signature_t<Set>> 0312 struct pickle_factory; 0313 0314 template <typename Get, typename Set, 0315 typename RetState, typename Self, typename NewInstance, typename ArgState> 0316 struct pickle_factory<Get, Set, RetState(Self), NewInstance(ArgState)> { 0317 static_assert(std::is_same<intrinsic_t<RetState>, intrinsic_t<ArgState>>::value, 0318 "The type returned by `__getstate__` must be the same " 0319 "as the argument accepted by `__setstate__`"); 0320 0321 remove_reference_t<Get> get; 0322 remove_reference_t<Set> set; 0323 0324 pickle_factory(Get get, Set set) 0325 : get(std::forward<Get>(get)), set(std::forward<Set>(set)) { } 0326 0327 template <typename Class, typename... Extra> 0328 void execute(Class &cl, const Extra &...extra) && { 0329 cl.def("__getstate__", std::move(get)); 0330 0331 #if defined(PYBIND11_CPP14) 0332 cl.def("__setstate__", [func = std::move(set)] 0333 #else 0334 auto &func = set; 0335 cl.def("__setstate__", [func] 0336 #endif 0337 (value_and_holder &v_h, ArgState state) { 0338 setstate<Class>(v_h, func(std::forward<ArgState>(state)), 0339 Py_TYPE(v_h.inst) != v_h.type->type); 0340 }, is_new_style_constructor(), extra...); 0341 } 0342 }; 0343 0344 PYBIND11_NAMESPACE_END(initimpl) 0345 PYBIND11_NAMESPACE_END(detail) 0346 PYBIND11_NAMESPACE_END(pybind11)