diff options
Diffstat (limited to 'ext/pybind11/include/pybind11/cast.h')
-rw-r--r-- | ext/pybind11/include/pybind11/cast.h | 1257 |
1 files changed, 853 insertions, 404 deletions
diff --git a/ext/pybind11/include/pybind11/cast.h b/ext/pybind11/include/pybind11/cast.h index fe19075e4..eab904bee 100644 --- a/ext/pybind11/include/pybind11/cast.h +++ b/ext/pybind11/include/pybind11/cast.h @@ -11,97 +11,184 @@ #pragma once #include "pytypes.h" -#include "typeid.h" -#include "descr.h" +#include "detail/typeid.h" +#include "detail/descr.h" +#include "detail/internals.h" #include <array> #include <limits> +#include <tuple> + +#if defined(PYBIND11_CPP17) +# if defined(__has_include) +# if __has_include(<string_view>) +# define PYBIND11_HAS_STRING_VIEW +# endif +# elif defined(_MSC_VER) +# define PYBIND11_HAS_STRING_VIEW +# endif +#endif +#ifdef PYBIND11_HAS_STRING_VIEW +#include <string_view> +#endif -NAMESPACE_BEGIN(pybind11) +NAMESPACE_BEGIN(PYBIND11_NAMESPACE) NAMESPACE_BEGIN(detail) -inline PyTypeObject *make_static_property_type(); -inline PyTypeObject *make_default_metaclass(); - -/// Additional type information which does not fit into the PyTypeObject -struct type_info { - PyTypeObject *type; - size_t type_size; - void *(*operator_new)(size_t); - void (*init_holder)(PyObject *, const void *); - void (*dealloc)(PyObject *); - std::vector<PyObject *(*)(PyObject *, PyTypeObject *)> implicit_conversions; - std::vector<std::pair<const std::type_info *, void *(*)(void *)>> implicit_casts; - std::vector<bool (*)(PyObject *, void *&)> *direct_conversions; - buffer_info *(*get_buffer)(PyObject *, void *) = nullptr; - void *get_buffer_data = nullptr; - /** A simple type never occurs as a (direct or indirect) parent - * of a class that makes use of multiple inheritance */ - bool simple_type = true; - /* for base vs derived holder_type checks */ - bool default_holder = true; + +/// A life support system for temporary objects created by `type_caster::load()`. +/// Adding a patient will keep it alive up until the enclosing function returns. +class loader_life_support { +public: + /// A new patient frame is created when a function is entered + loader_life_support() { + get_internals().loader_patient_stack.push_back(nullptr); + } + + /// ... and destroyed after it returns + ~loader_life_support() { + auto &stack = get_internals().loader_patient_stack; + if (stack.empty()) + pybind11_fail("loader_life_support: internal error"); + + auto ptr = stack.back(); + stack.pop_back(); + Py_CLEAR(ptr); + + // A heuristic to reduce the stack's capacity (e.g. after long recursive calls) + if (stack.capacity() > 16 && stack.size() != 0 && stack.capacity() / stack.size() > 2) + stack.shrink_to_fit(); + } + + /// This can only be used inside a pybind11-bound function, either by `argument_loader` + /// at argument preparation time or by `py::cast()` at execution time. + PYBIND11_NOINLINE static void add_patient(handle h) { + auto &stack = get_internals().loader_patient_stack; + if (stack.empty()) + throw cast_error("When called outside a bound function, py::cast() cannot " + "do Python -> C++ conversions which require the creation " + "of temporary values"); + + auto &list_ptr = stack.back(); + if (list_ptr == nullptr) { + list_ptr = PyList_New(1); + if (!list_ptr) + pybind11_fail("loader_life_support: error allocating list"); + PyList_SET_ITEM(list_ptr, 0, h.inc_ref().ptr()); + } else { + auto result = PyList_Append(list_ptr, h.ptr()); + if (result == -1) + pybind11_fail("loader_life_support: error adding patient"); + } + } }; -PYBIND11_NOINLINE inline internals &get_internals() { - static internals *internals_ptr = nullptr; - if (internals_ptr) - return *internals_ptr; - handle builtins(PyEval_GetBuiltins()); - const char *id = PYBIND11_INTERNALS_ID; - if (builtins.contains(id) && isinstance<capsule>(builtins[id])) { - internals_ptr = capsule(builtins[id]); - } else { - internals_ptr = new internals(); - #if defined(WITH_THREAD) - PyEval_InitThreads(); - PyThreadState *tstate = PyThreadState_Get(); - internals_ptr->tstate = PyThread_create_key(); - PyThread_set_key_value(internals_ptr->tstate, tstate); - internals_ptr->istate = tstate->interp; - #endif - builtins[id] = capsule(internals_ptr); - internals_ptr->registered_exception_translators.push_front( - [](std::exception_ptr p) -> void { - try { - if (p) std::rethrow_exception(p); - } catch (error_already_set &e) { e.restore(); return; - } catch (const builtin_exception &e) { e.set_error(); return; - } catch (const std::bad_alloc &e) { PyErr_SetString(PyExc_MemoryError, e.what()); return; - } catch (const std::domain_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return; - } catch (const std::invalid_argument &e) { PyErr_SetString(PyExc_ValueError, e.what()); return; - } catch (const std::length_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return; - } catch (const std::out_of_range &e) { PyErr_SetString(PyExc_IndexError, e.what()); return; - } catch (const std::range_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return; - } catch (const std::exception &e) { PyErr_SetString(PyExc_RuntimeError, e.what()); return; - } catch (...) { - PyErr_SetString(PyExc_RuntimeError, "Caught an unknown exception!"); - return; +// Gets the cache entry for the given type, creating it if necessary. The return value is the pair +// returned by emplace, i.e. an iterator for the entry and a bool set to `true` if the entry was +// just created. +inline std::pair<decltype(internals::registered_types_py)::iterator, bool> all_type_info_get_cache(PyTypeObject *type); + +// Populates a just-created cache entry. +PYBIND11_NOINLINE inline void all_type_info_populate(PyTypeObject *t, std::vector<type_info *> &bases) { + std::vector<PyTypeObject *> check; + for (handle parent : reinterpret_borrow<tuple>(t->tp_bases)) + check.push_back((PyTypeObject *) parent.ptr()); + + auto const &type_dict = get_internals().registered_types_py; + for (size_t i = 0; i < check.size(); i++) { + auto type = check[i]; + // Ignore Python2 old-style class super type: + if (!PyType_Check((PyObject *) type)) continue; + + // Check `type` in the current set of registered python types: + auto it = type_dict.find(type); + if (it != type_dict.end()) { + // We found a cache entry for it, so it's either pybind-registered or has pre-computed + // pybind bases, but we have to make sure we haven't already seen the type(s) before: we + // want to follow Python/virtual C++ rules that there should only be one instance of a + // common base. + for (auto *tinfo : it->second) { + // NB: Could use a second set here, rather than doing a linear search, but since + // having a large number of immediate pybind11-registered types seems fairly + // unlikely, that probably isn't worthwhile. + bool found = false; + for (auto *known : bases) { + if (known == tinfo) { found = true; break; } } + if (!found) bases.push_back(tinfo); + } + } + else if (type->tp_bases) { + // It's some python type, so keep follow its bases classes to look for one or more + // registered types + if (i + 1 == check.size()) { + // When we're at the end, we can pop off the current element to avoid growing + // `check` when adding just one base (which is typical--i.e. when there is no + // multiple inheritance) + check.pop_back(); + i--; } - ); - internals_ptr->static_property_type = make_static_property_type(); - internals_ptr->default_metaclass = make_default_metaclass(); + for (handle parent : reinterpret_borrow<tuple>(type->tp_bases)) + check.push_back((PyTypeObject *) parent.ptr()); + } } - return *internals_ptr; } +/** + * Extracts vector of type_info pointers of pybind-registered roots of the given Python type. Will + * be just 1 pybind type for the Python type of a pybind-registered class, or for any Python-side + * derived class that uses single inheritance. Will contain as many types as required for a Python + * class that uses multiple inheritance to inherit (directly or indirectly) from multiple + * pybind-registered classes. Will be empty if neither the type nor any base classes are + * pybind-registered. + * + * The value is cached for the lifetime of the Python type. + */ +inline const std::vector<detail::type_info *> &all_type_info(PyTypeObject *type) { + auto ins = all_type_info_get_cache(type); + if (ins.second) + // New cache entry: populate it + all_type_info_populate(type, ins.first->second); + + return ins.first->second; +} + +/** + * Gets a single pybind11 type info for a python type. Returns nullptr if neither the type nor any + * ancestors are pybind11-registered. Throws an exception if there are multiple bases--use + * `all_type_info` instead if you want to support multiple bases. + */ PYBIND11_NOINLINE inline detail::type_info* get_type_info(PyTypeObject *type) { - auto const &type_dict = get_internals().registered_types_py; - do { - auto it = type_dict.find(type); - if (it != type_dict.end()) - return (detail::type_info *) it->second; - type = type->tp_base; - if (!type) - return nullptr; - } while (true); + auto &bases = all_type_info(type); + if (bases.size() == 0) + return nullptr; + if (bases.size() > 1) + pybind11_fail("pybind11::detail::get_type_info: type has multiple pybind11-registered bases"); + return bases.front(); } -PYBIND11_NOINLINE inline detail::type_info *get_type_info(const std::type_info &tp, - bool throw_if_missing = false) { - auto &types = get_internals().registered_types_cpp; +inline detail::type_info *get_local_type_info(const std::type_index &tp) { + auto &locals = registered_local_types_cpp(); + auto it = locals.find(tp); + if (it != locals.end()) + return it->second; + return nullptr; +} - auto it = types.find(std::type_index(tp)); +inline detail::type_info *get_global_type_info(const std::type_index &tp) { + auto &types = get_internals().registered_types_cpp; + auto it = types.find(tp); if (it != types.end()) - return (detail::type_info *) it->second; + return it->second; + return nullptr; +} + +/// Return the type info for a given C++ type; on lookup failure can either throw or return nullptr. +PYBIND11_NOINLINE inline detail::type_info *get_type_info(const std::type_index &tp, + bool throw_if_missing = false) { + if (auto ltype = get_local_type_info(tp)) + return ltype; + if (auto gtype = get_global_type_info(tp)) + return gtype; + if (throw_if_missing) { std::string tname = tp.name(); detail::clean_type_id(tname); @@ -115,6 +202,199 @@ PYBIND11_NOINLINE inline handle get_type_handle(const std::type_info &tp, bool t return handle(type_info ? ((PyObject *) type_info->type) : nullptr); } +struct value_and_holder { + instance *inst; + size_t index; + const detail::type_info *type; + void **vh; + + // Main constructor for a found value/holder: + value_and_holder(instance *i, const detail::type_info *type, size_t vpos, size_t index) : + inst{i}, index{index}, type{type}, + vh{inst->simple_layout ? inst->simple_value_holder : &inst->nonsimple.values_and_holders[vpos]} + {} + + // Default constructor (used to signal a value-and-holder not found by get_value_and_holder()) + value_and_holder() : inst{nullptr} {} + + // Used for past-the-end iterator + value_and_holder(size_t index) : index{index} {} + + template <typename V = void> V *&value_ptr() const { + return reinterpret_cast<V *&>(vh[0]); + } + // True if this `value_and_holder` has a non-null value pointer + explicit operator bool() const { return value_ptr(); } + + template <typename H> H &holder() const { + return reinterpret_cast<H &>(vh[1]); + } + bool holder_constructed() const { + return inst->simple_layout + ? inst->simple_holder_constructed + : inst->nonsimple.status[index] & instance::status_holder_constructed; + } + void set_holder_constructed(bool v = true) { + if (inst->simple_layout) + inst->simple_holder_constructed = v; + else if (v) + inst->nonsimple.status[index] |= instance::status_holder_constructed; + else + inst->nonsimple.status[index] &= (uint8_t) ~instance::status_holder_constructed; + } + bool instance_registered() const { + return inst->simple_layout + ? inst->simple_instance_registered + : inst->nonsimple.status[index] & instance::status_instance_registered; + } + void set_instance_registered(bool v = true) { + if (inst->simple_layout) + inst->simple_instance_registered = v; + else if (v) + inst->nonsimple.status[index] |= instance::status_instance_registered; + else + inst->nonsimple.status[index] &= (uint8_t) ~instance::status_instance_registered; + } +}; + +// Container for accessing and iterating over an instance's values/holders +struct values_and_holders { +private: + instance *inst; + using type_vec = std::vector<detail::type_info *>; + const type_vec &tinfo; + +public: + values_and_holders(instance *inst) : inst{inst}, tinfo(all_type_info(Py_TYPE(inst))) {} + + struct iterator { + private: + instance *inst; + const type_vec *types; + value_and_holder curr; + friend struct values_and_holders; + iterator(instance *inst, const type_vec *tinfo) + : inst{inst}, types{tinfo}, + curr(inst /* instance */, + types->empty() ? nullptr : (*types)[0] /* type info */, + 0, /* vpos: (non-simple types only): the first vptr comes first */ + 0 /* index */) + {} + // Past-the-end iterator: + iterator(size_t end) : curr(end) {} + public: + bool operator==(const iterator &other) { return curr.index == other.curr.index; } + bool operator!=(const iterator &other) { return curr.index != other.curr.index; } + iterator &operator++() { + if (!inst->simple_layout) + curr.vh += 1 + (*types)[curr.index]->holder_size_in_ptrs; + ++curr.index; + curr.type = curr.index < types->size() ? (*types)[curr.index] : nullptr; + return *this; + } + value_and_holder &operator*() { return curr; } + value_and_holder *operator->() { return &curr; } + }; + + iterator begin() { return iterator(inst, &tinfo); } + iterator end() { return iterator(tinfo.size()); } + + iterator find(const type_info *find_type) { + auto it = begin(), endit = end(); + while (it != endit && it->type != find_type) ++it; + return it; + } + + size_t size() { return tinfo.size(); } +}; + +/** + * Extracts C++ value and holder pointer references from an instance (which may contain multiple + * values/holders for python-side multiple inheritance) that match the given type. Throws an error + * if the given type (or ValueType, if omitted) is not a pybind11 base of the given instance. If + * `find_type` is omitted (or explicitly specified as nullptr) the first value/holder are returned, + * regardless of type (and the resulting .type will be nullptr). + * + * The returned object should be short-lived: in particular, it must not outlive the called-upon + * instance. + */ +PYBIND11_NOINLINE inline value_and_holder instance::get_value_and_holder(const type_info *find_type /*= nullptr default in common.h*/, bool throw_if_missing /*= true in common.h*/) { + // Optimize common case: + if (!find_type || Py_TYPE(this) == find_type->type) + return value_and_holder(this, find_type, 0, 0); + + detail::values_and_holders vhs(this); + auto it = vhs.find(find_type); + if (it != vhs.end()) + return *it; + + if (!throw_if_missing) + return value_and_holder(); + +#if defined(NDEBUG) + pybind11_fail("pybind11::detail::instance::get_value_and_holder: " + "type is not a pybind11 base of the given instance " + "(compile in debug mode for type details)"); +#else + pybind11_fail("pybind11::detail::instance::get_value_and_holder: `" + + std::string(find_type->type->tp_name) + "' is not a pybind11 base of the given `" + + std::string(Py_TYPE(this)->tp_name) + "' instance"); +#endif +} + +PYBIND11_NOINLINE inline void instance::allocate_layout() { + auto &tinfo = all_type_info(Py_TYPE(this)); + + const size_t n_types = tinfo.size(); + + if (n_types == 0) + pybind11_fail("instance allocation failed: new instance has no pybind11-registered base types"); + + simple_layout = + n_types == 1 && tinfo.front()->holder_size_in_ptrs <= instance_simple_holder_in_ptrs(); + + // Simple path: no python-side multiple inheritance, and a small-enough holder + if (simple_layout) { + simple_value_holder[0] = nullptr; + simple_holder_constructed = false; + simple_instance_registered = false; + } + else { // multiple base types or a too-large holder + // Allocate space to hold: [v1*][h1][v2*][h2]...[bb...] where [vN*] is a value pointer, + // [hN] is the (uninitialized) holder instance for value N, and [bb...] is a set of bool + // values that tracks whether each associated holder has been initialized. Each [block] is + // padded, if necessary, to an integer multiple of sizeof(void *). + size_t space = 0; + for (auto t : tinfo) { + space += 1; // value pointer + space += t->holder_size_in_ptrs; // holder instance + } + size_t flags_at = space; + space += size_in_ptrs(n_types); // status bytes (holder_constructed and instance_registered) + + // Allocate space for flags, values, and holders, and initialize it to 0 (flags and values, + // in particular, need to be 0). Use Python's memory allocation functions: in Python 3.6 + // they default to using pymalloc, which is designed to be efficient for small allocations + // like the one we're doing here; in earlier versions (and for larger allocations) they are + // just wrappers around malloc. +#if PY_VERSION_HEX >= 0x03050000 + nonsimple.values_and_holders = (void **) PyMem_Calloc(space, sizeof(void *)); + if (!nonsimple.values_and_holders) throw std::bad_alloc(); +#else + nonsimple.values_and_holders = (void **) PyMem_New(void *, space); + if (!nonsimple.values_and_holders) throw std::bad_alloc(); + std::memset(nonsimple.values_and_holders, 0, space * sizeof(void *)); +#endif + nonsimple.status = reinterpret_cast<uint8_t *>(&nonsimple.values_and_holders[flags_at]); + } + owned = true; +} + +PYBIND11_NOINLINE inline void instance::deallocate_layout() { + if (!simple_layout) + PyMem_Free(nonsimple.values_and_holders); +} + PYBIND11_NOINLINE inline bool isinstance_generic(handle obj, const std::type_info &tp) { handle type = detail::get_type_handle(tp, false); if (!type) @@ -163,7 +443,6 @@ PYBIND11_NOINLINE inline std::string error_string() { handle(frame->f_code->co_name).cast<std::string>() + "\n"; frame = frame->f_back; } - trace = trace->tb_next; } #endif @@ -174,9 +453,10 @@ PYBIND11_NOINLINE inline handle get_object_handle(const void *ptr, const detail: auto &instances = get_internals().registered_instances; auto range = instances.equal_range(ptr); for (auto it = range.first; it != range.second; ++it) { - auto instance_type = detail::get_type_info(Py_TYPE(it->second)); - if (instance_type && instance_type == type) - return handle((PyObject *) it->second); + for (auto vh : values_and_holders(it->second)) { + if (vh.type == type) + return handle((PyObject *) it->second); + } } return handle(); } @@ -195,136 +475,63 @@ inline PyThreadState *get_thread_state_unchecked() { #endif } -// Forward declaration +// Forward declarations inline void keep_alive_impl(handle nurse, handle patient); +inline PyObject *make_new_instance(PyTypeObject *type); class type_caster_generic { public: PYBIND11_NOINLINE type_caster_generic(const std::type_info &type_info) - : typeinfo(get_type_info(type_info)) { } - - PYBIND11_NOINLINE bool load(handle src, bool convert) { - if (!src) - return false; - return load(src, convert, Py_TYPE(src.ptr())); - } - - bool load(handle src, bool convert, PyTypeObject *tobj) { - if (!src || !typeinfo) - return false; - if (src.is_none()) { - value = nullptr; - return true; - } + : typeinfo(get_type_info(type_info)), cpptype(&type_info) { } - if (typeinfo->simple_type) { /* Case 1: no multiple inheritance etc. involved */ - /* Check if we can safely perform a reinterpret-style cast */ - if (PyType_IsSubtype(tobj, typeinfo->type)) { - value = reinterpret_cast<instance<void> *>(src.ptr())->value; - return true; - } - } else { /* Case 2: multiple inheritance */ - /* Check if we can safely perform a reinterpret-style cast */ - if (tobj == typeinfo->type) { - value = reinterpret_cast<instance<void> *>(src.ptr())->value; - return true; - } + type_caster_generic(const type_info *typeinfo) + : typeinfo(typeinfo), cpptype(typeinfo ? typeinfo->cpptype : nullptr) { } - /* If this is a python class, also check the parents recursively */ - auto const &type_dict = get_internals().registered_types_py; - bool new_style_class = PyType_Check((PyObject *) tobj); - if (type_dict.find(tobj) == type_dict.end() && new_style_class && tobj->tp_bases) { - auto parents = reinterpret_borrow<tuple>(tobj->tp_bases); - for (handle parent : parents) { - bool result = load(src, convert, (PyTypeObject *) parent.ptr()); - if (result) - return true; - } - } - - /* Try implicit casts */ - for (auto &cast : typeinfo->implicit_casts) { - type_caster_generic sub_caster(*cast.first); - if (sub_caster.load(src, convert)) { - value = cast.second(sub_caster.value); - return true; - } - } - } - - /* Perform an implicit conversion */ - if (convert) { - for (auto &converter : typeinfo->implicit_conversions) { - temp = reinterpret_steal<object>(converter(src.ptr(), typeinfo->type)); - if (load(temp, false)) - return true; - } - for (auto &converter : *typeinfo->direct_conversions) { - if (converter(src.ptr(), value)) - return true; - } - } - return false; + bool load(handle src, bool convert) { + return load_impl<type_caster_generic>(src, convert); } PYBIND11_NOINLINE static handle cast(const void *_src, return_value_policy policy, handle parent, - const std::type_info *type_info, - const std::type_info *type_info_backup, + const detail::type_info *tinfo, void *(*copy_constructor)(const void *), void *(*move_constructor)(const void *), const void *existing_holder = nullptr) { - void *src = const_cast<void *>(_src); - if (src == nullptr) - return none().inc_ref(); - - auto &internals = get_internals(); - - auto it = internals.registered_types_cpp.find(std::type_index(*type_info)); - if (it == internals.registered_types_cpp.end()) { - type_info = type_info_backup; - it = internals.registered_types_cpp.find(std::type_index(*type_info)); - } - - if (it == internals.registered_types_cpp.end()) { - std::string tname = type_info->name(); - detail::clean_type_id(tname); - std::string msg = "Unregistered type : " + tname; - PyErr_SetString(PyExc_TypeError, msg.c_str()); + if (!tinfo) // no type info: error will be set already return handle(); - } - auto tinfo = (const detail::type_info *) it->second; + void *src = const_cast<void *>(_src); + if (src == nullptr) + return none().release(); - auto it_instances = internals.registered_instances.equal_range(src); + auto it_instances = get_internals().registered_instances.equal_range(src); for (auto it_i = it_instances.first; it_i != it_instances.second; ++it_i) { - auto instance_type = detail::get_type_info(Py_TYPE(it_i->second)); - if (instance_type && instance_type == tinfo) - return handle((PyObject *) it_i->second).inc_ref(); + for (auto instance_type : detail::all_type_info(Py_TYPE(it_i->second))) { + if (instance_type && same_type(*instance_type->cpptype, *tinfo->cpptype)) + return handle((PyObject *) it_i->second).inc_ref(); + } } - auto inst = reinterpret_steal<object>(PyType_GenericAlloc(tinfo->type, 0)); - - auto wrapper = (instance<void> *) inst.ptr(); - - wrapper->value = nullptr; + auto inst = reinterpret_steal<object>(make_new_instance(tinfo->type)); + auto wrapper = reinterpret_cast<instance *>(inst.ptr()); wrapper->owned = false; + void *&valueptr = values_and_holders(wrapper).begin()->value_ptr(); switch (policy) { case return_value_policy::automatic: case return_value_policy::take_ownership: - wrapper->value = src; + valueptr = src; wrapper->owned = true; break; case return_value_policy::automatic_reference: case return_value_policy::reference: - wrapper->value = src; + valueptr = src; wrapper->owned = false; break; case return_value_policy::copy: if (copy_constructor) - wrapper->value = copy_constructor(src); + valueptr = copy_constructor(src); else throw cast_error("return_value_policy = copy, but the " "object is non-copyable!"); @@ -333,9 +540,9 @@ public: case return_value_policy::move: if (move_constructor) - wrapper->value = move_constructor(src); + valueptr = move_constructor(src); else if (copy_constructor) - wrapper->value = copy_constructor(src); + valueptr = copy_constructor(src); else throw cast_error("return_value_policy = move, but the " "object is neither movable nor copyable!"); @@ -343,33 +550,210 @@ public: break; case return_value_policy::reference_internal: - wrapper->value = src; + valueptr = src; wrapper->owned = false; - detail::keep_alive_impl(inst, parent); + keep_alive_impl(inst, parent); break; default: throw cast_error("unhandled return_value_policy: should not happen!"); } - tinfo->init_holder(inst.ptr(), existing_holder); - - internals.registered_instances.emplace(wrapper->value, inst.ptr()); + tinfo->init_instance(wrapper, existing_holder); return inst.release(); } -protected: + // Base methods for generic caster; there are overridden in copyable_holder_caster + void load_value(value_and_holder &&v_h) { + auto *&vptr = v_h.value_ptr(); + // Lazy allocation for unallocated values: + if (vptr == nullptr) { + auto *type = v_h.type ? v_h.type : typeinfo; + vptr = type->operator_new(type->type_size); + } + value = vptr; + } + bool try_implicit_casts(handle src, bool convert) { + for (auto &cast : typeinfo->implicit_casts) { + type_caster_generic sub_caster(*cast.first); + if (sub_caster.load(src, convert)) { + value = cast.second(sub_caster.value); + return true; + } + } + return false; + } + bool try_direct_conversions(handle src) { + for (auto &converter : *typeinfo->direct_conversions) { + if (converter(src.ptr(), value)) + return true; + } + return false; + } + void check_holder_compat() {} + + PYBIND11_NOINLINE static void *local_load(PyObject *src, const type_info *ti) { + auto caster = type_caster_generic(ti); + if (caster.load(src, false)) + return caster.value; + return nullptr; + } + + /// Try to load with foreign typeinfo, if available. Used when there is no + /// native typeinfo, or when the native one wasn't able to produce a value. + PYBIND11_NOINLINE bool try_load_foreign_module_local(handle src) { + constexpr auto *local_key = PYBIND11_MODULE_LOCAL_ID; + const auto pytype = src.get_type(); + if (!hasattr(pytype, local_key)) + return false; + + type_info *foreign_typeinfo = reinterpret_borrow<capsule>(getattr(pytype, local_key)); + // Only consider this foreign loader if actually foreign and is a loader of the correct cpp type + if (foreign_typeinfo->module_local_load == &local_load + || (cpptype && !same_type(*cpptype, *foreign_typeinfo->cpptype))) + return false; + + if (auto result = foreign_typeinfo->module_local_load(src.ptr(), foreign_typeinfo)) { + value = result; + return true; + } + return false; + } + + // Implementation of `load`; this takes the type of `this` so that it can dispatch the relevant + // bits of code between here and copyable_holder_caster where the two classes need different + // logic (without having to resort to virtual inheritance). + template <typename ThisT> + PYBIND11_NOINLINE bool load_impl(handle src, bool convert) { + if (!src) return false; + if (!typeinfo) return try_load_foreign_module_local(src); + if (src.is_none()) { + // Defer accepting None to other overloads (if we aren't in convert mode): + if (!convert) return false; + value = nullptr; + return true; + } + + auto &this_ = static_cast<ThisT &>(*this); + this_.check_holder_compat(); + + PyTypeObject *srctype = Py_TYPE(src.ptr()); + + // Case 1: If src is an exact type match for the target type then we can reinterpret_cast + // the instance's value pointer to the target type: + if (srctype == typeinfo->type) { + this_.load_value(reinterpret_cast<instance *>(src.ptr())->get_value_and_holder()); + return true; + } + // Case 2: We have a derived class + else if (PyType_IsSubtype(srctype, typeinfo->type)) { + auto &bases = all_type_info(srctype); + bool no_cpp_mi = typeinfo->simple_type; + + // Case 2a: the python type is a Python-inherited derived class that inherits from just + // one simple (no MI) pybind11 class, or is an exact match, so the C++ instance is of + // the right type and we can use reinterpret_cast. + // (This is essentially the same as case 2b, but because not using multiple inheritance + // is extremely common, we handle it specially to avoid the loop iterator and type + // pointer lookup overhead) + if (bases.size() == 1 && (no_cpp_mi || bases.front()->type == typeinfo->type)) { + this_.load_value(reinterpret_cast<instance *>(src.ptr())->get_value_and_holder()); + return true; + } + // Case 2b: the python type inherits from multiple C++ bases. Check the bases to see if + // we can find an exact match (or, for a simple C++ type, an inherited match); if so, we + // can safely reinterpret_cast to the relevant pointer. + else if (bases.size() > 1) { + for (auto base : bases) { + if (no_cpp_mi ? PyType_IsSubtype(base->type, typeinfo->type) : base->type == typeinfo->type) { + this_.load_value(reinterpret_cast<instance *>(src.ptr())->get_value_and_holder(base)); + return true; + } + } + } + + // Case 2c: C++ multiple inheritance is involved and we couldn't find an exact type match + // in the registered bases, above, so try implicit casting (needed for proper C++ casting + // when MI is involved). + if (this_.try_implicit_casts(src, convert)) + return true; + } + + // Perform an implicit conversion + if (convert) { + for (auto &converter : typeinfo->implicit_conversions) { + auto temp = reinterpret_steal<object>(converter(src.ptr(), typeinfo->type)); + if (load_impl<ThisT>(temp, false)) { + loader_life_support::add_patient(temp); + return true; + } + } + if (this_.try_direct_conversions(src)) + return true; + } + + // Failed to match local typeinfo. Try again with global. + if (typeinfo->module_local) { + if (auto gtype = get_global_type_info(*typeinfo->cpptype)) { + typeinfo = gtype; + return load(src, false); + } + } + + // Global typeinfo has precedence over foreign module_local + return try_load_foreign_module_local(src); + } + + + // Called to do type lookup and wrap the pointer and type in a pair when a dynamic_cast + // isn't needed or can't be used. If the type is unknown, sets the error and returns a pair + // with .second = nullptr. (p.first = nullptr is not an error: it becomes None). + PYBIND11_NOINLINE static std::pair<const void *, const type_info *> src_and_type( + const void *src, const std::type_info &cast_type, const std::type_info *rtti_type = nullptr) { + if (auto *tpi = get_type_info(cast_type)) + return {src, const_cast<const type_info *>(tpi)}; + + // Not found, set error: + std::string tname = rtti_type ? rtti_type->name() : cast_type.name(); + detail::clean_type_id(tname); + std::string msg = "Unregistered type : " + tname; + PyErr_SetString(PyExc_TypeError, msg.c_str()); + return {nullptr, nullptr}; + } + const type_info *typeinfo = nullptr; + const std::type_info *cpptype = nullptr; void *value = nullptr; - object temp; }; -/* Determine suitable casting operator */ +/** + * Determine suitable casting operator for pointer-or-lvalue-casting type casters. The type caster + * needs to provide `operator T*()` and `operator T&()` operators. + * + * If the type supports moving the value away via an `operator T&&() &&` method, it should use + * `movable_cast_op_type` instead. + */ +template <typename T> +using cast_op_type = + conditional_t<std::is_pointer<remove_reference_t<T>>::value, + typename std::add_pointer<intrinsic_t<T>>::type, + typename std::add_lvalue_reference<intrinsic_t<T>>::type>; + +/** + * Determine suitable casting operator for a type caster with a movable value. Such a type caster + * needs to provide `operator T*()`, `operator T&()`, and `operator T&&() &&`. The latter will be + * called in appropriate contexts where the value can be moved rather than copied. + * + * These operator are automatically provided when using the PYBIND11_TYPE_CASTER macro. + */ template <typename T> -using cast_op_type = typename std::conditional<std::is_pointer<typename std::remove_reference<T>::type>::value, - typename std::add_pointer<intrinsic_t<T>>::type, - typename std::add_lvalue_reference<intrinsic_t<T>>::type>::type; +using movable_cast_op_type = + conditional_t<std::is_pointer<typename std::remove_reference<T>::type>::value, + typename std::add_pointer<intrinsic_t<T>>::type, + conditional_t<std::is_rvalue_reference<T>::value, + typename std::add_rvalue_reference<intrinsic_t<T>>::type, + typename std::add_lvalue_reference<intrinsic_t<T>>::type>>; // std::is_copy_constructible isn't quite enough: it lets std::vector<T> (and similar) through when // T is non-copyable, but code containing such a copy constructor fails to actually compile. @@ -378,10 +762,17 @@ template <typename T, typename SFINAE = void> struct is_copy_constructible : std // Specialization for types that appear to be copy constructible but also look like stl containers // (we specifically check for: has `value_type` and `reference` with `reference = value_type&`): if // so, copy constructability depends on whether the value_type is copy constructible. -template <typename Container> struct is_copy_constructible<Container, enable_if_t< - std::is_copy_constructible<Container>::value && - std::is_same<typename Container::value_type &, typename Container::reference>::value - >> : std::is_copy_constructible<typename Container::value_type> {}; +template <typename Container> struct is_copy_constructible<Container, enable_if_t<all_of< + std::is_copy_constructible<Container>, + std::is_same<typename Container::value_type &, typename Container::reference> + >::value>> : is_copy_constructible<typename Container::value_type> {}; + +#if !defined(PYBIND11_CPP17) +// Likewise for std::pair before C++17 (which mandates that the copy constructor not exist when the +// two types aren't themselves copy constructible). +template <typename T1, typename T2> struct is_copy_constructible<std::pair<T1, T2>> + : all_of<is_copy_constructible<T1>, is_copy_constructible<T2>> {}; +#endif /// Generic type caster for objects stored on the heap template <typename type> class type_caster_base : public type_caster_generic { @@ -402,43 +793,71 @@ public: return cast(&src, return_value_policy::move, parent); } + // Returns a (pointer, type_info) pair taking care of necessary RTTI type lookup for a + // polymorphic type. If the instance isn't derived, returns the non-RTTI base version. + template <typename T = itype, enable_if_t<std::is_polymorphic<T>::value, int> = 0> + static std::pair<const void *, const type_info *> src_and_type(const itype *src) { + const void *vsrc = src; + auto &cast_type = typeid(itype); + const std::type_info *instance_type = nullptr; + if (vsrc) { + instance_type = &typeid(*src); + if (!same_type(cast_type, *instance_type)) { + // This is a base pointer to a derived type; if it is a pybind11-registered type, we + // can get the correct derived pointer (which may be != base pointer) by a + // dynamic_cast to most derived type: + if (auto *tpi = get_type_info(*instance_type)) + return {dynamic_cast<const void *>(src), const_cast<const type_info *>(tpi)}; + } + } + // Otherwise we have either a nullptr, an `itype` pointer, or an unknown derived pointer, so + // don't do a cast + return type_caster_generic::src_and_type(vsrc, cast_type, instance_type); + } + + // Non-polymorphic type, so no dynamic casting; just call the generic version directly + template <typename T = itype, enable_if_t<!std::is_polymorphic<T>::value, int> = 0> + static std::pair<const void *, const type_info *> src_and_type(const itype *src) { + return type_caster_generic::src_and_type(src, typeid(itype)); + } + static handle cast(const itype *src, return_value_policy policy, handle parent) { + auto st = src_and_type(src); return type_caster_generic::cast( - src, policy, parent, src ? &typeid(*src) : nullptr, &typeid(type), + st.first, policy, parent, st.second, make_copy_constructor(src), make_move_constructor(src)); } static handle cast_holder(const itype *src, const void *holder) { + auto st = src_and_type(src); return type_caster_generic::cast( - src, return_value_policy::take_ownership, {}, - src ? &typeid(*src) : nullptr, &typeid(type), + st.first, return_value_policy::take_ownership, {}, st.second, nullptr, nullptr, holder); } - template <typename T> using cast_op_type = pybind11::detail::cast_op_type<T>; + template <typename T> using cast_op_type = cast_op_type<T>; operator itype*() { return (type *) value; } operator itype&() { if (!value) throw reference_cast_error(); return *((itype *) value); } protected: - typedef void *(*Constructor)(const void *stream); -#if !defined(_MSC_VER) + using Constructor = void *(*)(const void *); + /* Only enabled when the types are {copy,move}-constructible *and* when the type - does not have a private operator new implementaton. */ - template <typename T = type, typename = enable_if_t<is_copy_constructible<T>::value>> static auto make_copy_constructor(const T *value) -> decltype(new T(*value), Constructor(nullptr)) { - return [](const void *arg) -> void * { return new T(*((const T *) arg)); }; } - template <typename T = type> static auto make_move_constructor(const T *value) -> decltype(new T(std::move(*((T *) value))), Constructor(nullptr)) { - return [](const void *arg) -> void * { return (void *) new T(std::move(*const_cast<T *>(reinterpret_cast<const T *>(arg)))); }; } -#else - /* Visual Studio 2015's SFINAE implementation doesn't yet handle the above robustly in all situations. - Use a workaround that only tests for constructibility for now. */ - template <typename T = type, typename = enable_if_t<is_copy_constructible<T>::value>> - static Constructor make_copy_constructor(const T *value) { - return [](const void *arg) -> void * { return new T(*((const T *)arg)); }; } - template <typename T = type, typename = enable_if_t<std::is_move_constructible<T>::value>> - static Constructor make_move_constructor(const T *value) { - return [](const void *arg) -> void * { return (void *) new T(std::move(*((T *)arg))); }; } -#endif + does not have a private operator new implementation. */ + template <typename T, typename = enable_if_t<is_copy_constructible<T>::value>> + static auto make_copy_constructor(const T *x) -> decltype(new T(*x), Constructor{}) { + return [](const void *arg) -> void * { + return new T(*reinterpret_cast<const T *>(arg)); + }; + } + + template <typename T, typename = enable_if_t<std::is_move_constructible<T>::value>> + static auto make_move_constructor(const T *x) -> decltype(new T(std::move(*const_cast<T *>(x))), Constructor{}) { + return [](const void *arg) -> void * { + return new T(std::move(*const_cast<T *>(reinterpret_cast<const T *>(arg)))); + }; + } static Constructor make_copy_constructor(...) { return nullptr; } static Constructor make_move_constructor(...) { return nullptr; } @@ -451,17 +870,30 @@ template <typename type> using make_caster = type_caster<intrinsic_t<type>>; template <typename T> typename make_caster<T>::template cast_op_type<T> cast_op(make_caster<T> &caster) { return caster.operator typename make_caster<T>::template cast_op_type<T>(); } -template <typename T> typename make_caster<T>::template cast_op_type<T> cast_op(make_caster<T> &&caster) { - return cast_op<T>(caster); +template <typename T> typename make_caster<T>::template cast_op_type<typename std::add_rvalue_reference<T>::type> +cast_op(make_caster<T> &&caster) { + return std::move(caster).operator + typename make_caster<T>::template cast_op_type<typename std::add_rvalue_reference<T>::type>(); } -template <typename type> class type_caster<std::reference_wrapper<type>> : public type_caster_base<type> { +template <typename type> class type_caster<std::reference_wrapper<type>> { +private: + using caster_t = make_caster<type>; + caster_t subcaster; + using subcaster_cast_op_type = typename caster_t::template cast_op_type<type>; + static_assert(std::is_same<typename std::remove_const<type>::type &, subcaster_cast_op_type>::value, + "std::reference_wrapper<T> caster requires T to have a caster with an `T &` operator"); public: + bool load(handle src, bool convert) { return subcaster.load(src, convert); } + static PYBIND11_DESCR name() { return caster_t::name(); } static handle cast(const std::reference_wrapper<type> &src, return_value_policy policy, handle parent) { - return type_caster_base<type>::cast(&src.get(), policy, parent); + // It is definitely wrong to take ownership of this pointer, so mask that rvp + if (policy == return_value_policy::take_ownership || policy == return_value_policy::automatic) + policy = return_value_policy::automatic_reference; + return caster_t::cast(&src.get(), policy, parent); } template <typename T> using cast_op_type = std::reference_wrapper<type>; - operator std::reference_wrapper<type>() { return std::ref(*((type *) this->value)); } + operator std::reference_wrapper<type>() { return subcaster.operator subcaster_cast_op_type&(); } }; #define PYBIND11_TYPE_CASTER(type, py_name) \ @@ -469,13 +901,19 @@ public: type value; \ public: \ static PYBIND11_DESCR name() { return type_descr(py_name); } \ - static handle cast(const type *src, return_value_policy policy, handle parent) { \ + template <typename T_, enable_if_t<std::is_same<type, remove_cv_t<T_>>::value, int> = 0> \ + static handle cast(T_ *src, return_value_policy policy, handle parent) { \ if (!src) return none().release(); \ - return cast(*src, policy, parent); \ + if (policy == return_value_policy::take_ownership) { \ + auto h = cast(std::move(*src), policy, parent); delete src; return h; \ + } else { \ + return cast(*src, policy, parent); \ + } \ } \ operator type*() { return &value; } \ operator type&() { return value; } \ - template <typename _T> using cast_op_type = pybind11::detail::cast_op_type<_T> + operator type&&() && { return std::move(value); } \ + template <typename T_> using cast_op_type = pybind11::detail::movable_cast_op_type<T_> template <typename CharT> using is_std_char_type = any_of< @@ -503,36 +941,32 @@ public: py_value = (py_type) PyFloat_AsDouble(src.ptr()); else return false; - } else if (sizeof(T) <= sizeof(long)) { - if (PyFloat_Check(src.ptr())) - return false; - if (std::is_signed<T>::value) - py_value = (py_type) PyLong_AsLong(src.ptr()); - else - py_value = (py_type) PyLong_AsUnsignedLong(src.ptr()); - } else { - if (PyFloat_Check(src.ptr())) - return false; - if (std::is_signed<T>::value) - py_value = (py_type) PYBIND11_LONG_AS_LONGLONG(src.ptr()); - else - py_value = (py_type) PYBIND11_LONG_AS_UNSIGNED_LONGLONG(src.ptr()); + } else if (PyFloat_Check(src.ptr())) { + return false; + } else if (std::is_unsigned<py_type>::value) { + py_value = as_unsigned<py_type>(src.ptr()); + } else { // signed integer: + py_value = sizeof(T) <= sizeof(long) + ? (py_type) PyLong_AsLong(src.ptr()) + : (py_type) PYBIND11_LONG_AS_LONGLONG(src.ptr()); } - if ((py_value == (py_type) -1 && PyErr_Occurred()) || - (std::is_integral<T>::value && sizeof(py_type) != sizeof(T) && - (py_value < (py_type) std::numeric_limits<T>::min() || - py_value > (py_type) std::numeric_limits<T>::max()))) { -#if PY_VERSION_HEX < 0x03000000 - bool type_error = PyErr_ExceptionMatches(PyExc_SystemError); + bool py_err = py_value == (py_type) -1 && PyErr_Occurred(); + if (py_err || (std::is_integral<T>::value && sizeof(py_type) != sizeof(T) && + (py_value < (py_type) std::numeric_limits<T>::min() || + py_value > (py_type) std::numeric_limits<T>::max()))) { + bool type_error = py_err && PyErr_ExceptionMatches( +#if PY_VERSION_HEX < 0x03000000 && !defined(PYPY_VERSION) + PyExc_SystemError #else - bool type_error = PyErr_ExceptionMatches(PyExc_TypeError); + PyExc_TypeError #endif + ); PyErr_Clear(); if (type_error && convert && PyNumber_Check(src.ptr())) { - auto tmp = reinterpret_borrow<object>(std::is_floating_point<T>::value - ? PyNumber_Float(src.ptr()) - : PyNumber_Long(src.ptr())); + auto tmp = reinterpret_steal<object>(std::is_floating_point<T>::value + ? PyNumber_Float(src.ptr()) + : PyNumber_Long(src.ptr())); PyErr_Clear(); return load(tmp, false); } @@ -564,7 +998,11 @@ public: template<typename T> struct void_caster { public: - bool load(handle, bool) { return false; } + bool load(handle src, bool) { + if (src && src.is_none()) + return true; + return false; + } static handle cast(T, return_value_policy /* policy */, handle /* parent */) { return none().inc_ref(); } @@ -592,8 +1030,9 @@ public: } /* Check if this is a C++ type */ - if (get_type_info((PyTypeObject *) h.get_type().ptr())) { - value = ((instance<void> *) h.ptr())->value; + auto &bases = all_type_info((PyTypeObject *) h.get_type().ptr()); + if (bases.size() == 1) { // Only allowing loading from a single-value type + value = values_and_holders(reinterpret_cast<instance *>(h.ptr())).begin()->value_ptr(); return true; } @@ -615,15 +1054,41 @@ private: void *value = nullptr; }; -template <> class type_caster<std::nullptr_t> : public type_caster<void_type> { }; +template <> class type_caster<std::nullptr_t> : public void_caster<std::nullptr_t> { }; template <> class type_caster<bool> { public: - bool load(handle src, bool) { + bool load(handle src, bool convert) { if (!src) return false; else if (src.ptr() == Py_True) { value = true; return true; } else if (src.ptr() == Py_False) { value = false; return true; } - else return false; + else if (convert || !strcmp("numpy.bool_", Py_TYPE(src.ptr())->tp_name)) { + // (allow non-implicit conversion for numpy booleans) + + Py_ssize_t res = -1; + if (src.is_none()) { + res = 0; // None is implicitly converted to False + } + #if defined(PYPY_VERSION) + // On PyPy, check that "__bool__" (or "__nonzero__" on Python 2.7) attr exists + else if (hasattr(src, PYBIND11_BOOL_ATTR)) { + res = PyObject_IsTrue(src.ptr()); + } + #else + // Alternate approach for CPython: this does the same as the above, but optimized + // using the CPython API so as to avoid an unneeded attribute lookup. + else if (auto tp_as_number = src.ptr()->ob_type->tp_as_number) { + if (PYBIND11_NB_BOOL(tp_as_number)) { + res = (*PYBIND11_NB_BOOL(tp_as_number))(src.ptr()); + } + } + #endif + if (res == 0 || res == 1) { + value = (bool) res; + return true; + } + } + return false; } static handle cast(bool src, return_value_policy /* policy */, handle /* parent */) { return handle(src ? Py_True : Py_False).inc_ref(); @@ -632,10 +1097,11 @@ public: }; // Helper class for UTF-{8,16,32} C++ stl strings: -template <typename CharT, class Traits, class Allocator> -struct type_caster<std::basic_string<CharT, Traits, Allocator>, enable_if_t<is_std_char_type<CharT>::value>> { +template <typename StringType, bool IsView = false> struct string_caster { + using CharT = typename StringType::value_type; + // Simplify life by being able to assume standard char sizes (the standard only guarantees - // minimums), but Python requires exact sizes + // minimums, but Python requires exact sizes) static_assert(!std::is_same<CharT, char>::value || sizeof(CharT) == 1, "Unsupported char size != 1"); static_assert(!std::is_same<CharT, char16_t>::value || sizeof(CharT) == 2, "Unsupported char16_t size != 2"); static_assert(!std::is_same<CharT, char32_t>::value || sizeof(CharT) == 4, "Unsupported char32_t size != 4"); @@ -644,8 +1110,6 @@ struct type_caster<std::basic_string<CharT, Traits, Allocator>, enable_if_t<is_s "Unsupported wchar_t size != 2/4"); static constexpr size_t UTF_N = 8 * sizeof(CharT); - using StringType = std::basic_string<CharT, Traits, Allocator>; - bool load(handle src, bool) { #if PY_MAJOR_VERSION < 3 object temp; @@ -655,11 +1119,16 @@ struct type_caster<std::basic_string<CharT, Traits, Allocator>, enable_if_t<is_s return false; } else if (!PyUnicode_Check(load_src.ptr())) { #if PY_MAJOR_VERSION >= 3 - return false; - // The below is a guaranteed failure in Python 3 when PyUnicode_Check returns false + return load_bytes(load_src); #else + if (sizeof(CharT) == 1) { + return load_bytes(load_src); + } + + // The below is a guaranteed failure in Python 3 when PyUnicode_Check returns false if (!PYBIND11_BYTES_CHECK(load_src.ptr())) return false; + temp = reinterpret_steal<object>(PyUnicode_FromObject(load_src.ptr())); if (!temp) { PyErr_Clear(); return false; } load_src = temp; @@ -674,11 +1143,16 @@ struct type_caster<std::basic_string<CharT, Traits, Allocator>, enable_if_t<is_s size_t length = (size_t) PYBIND11_BYTES_SIZE(utfNbytes.ptr()) / sizeof(CharT); if (UTF_N > 8) { buffer++; length--; } // Skip BOM for UTF-16/32 value = StringType(buffer, length); + + // If we're loading a string_view we need to keep the encoded Python object alive: + if (IsView) + loader_life_support::add_patient(utfNbytes); + return true; } static handle cast(const StringType &src, return_value_policy /* policy */, handle /* parent */) { - const char *buffer = reinterpret_cast<const char *>(src.c_str()); + const char *buffer = reinterpret_cast<const char *>(src.data()); ssize_t nbytes = ssize_t(src.size() * sizeof(CharT)); handle s = decode_utfN(buffer, nbytes); if (!s) throw error_already_set(); @@ -702,8 +1176,39 @@ private: return PyUnicode_Decode(buffer, nbytes, UTF_N == 8 ? "utf-8" : UTF_N == 16 ? "utf-16" : "utf-32", nullptr); #endif } + + // When loading into a std::string or char*, accept a bytes object as-is (i.e. + // without any encoding/decoding attempt). For other C++ char sizes this is a no-op. + // which supports loading a unicode from a str, doesn't take this path. + template <typename C = CharT> + bool load_bytes(enable_if_t<sizeof(C) == 1, handle> src) { + if (PYBIND11_BYTES_CHECK(src.ptr())) { + // We were passed a Python 3 raw bytes; accept it into a std::string or char* + // without any encoding attempt. + const char *bytes = PYBIND11_BYTES_AS_STRING(src.ptr()); + if (bytes) { + value = StringType(bytes, (size_t) PYBIND11_BYTES_SIZE(src.ptr())); + return true; + } + } + + return false; + } + + template <typename C = CharT> + bool load_bytes(enable_if_t<sizeof(C) != 1, handle>) { return false; } }; +template <typename CharT, class Traits, class Allocator> +struct type_caster<std::basic_string<CharT, Traits, Allocator>, enable_if_t<is_std_char_type<CharT>::value>> + : string_caster<std::basic_string<CharT, Traits, Allocator>> {}; + +#ifdef PYBIND11_HAS_STRING_VIEW +template <typename CharT, class Traits> +struct type_caster<std::basic_string_view<CharT, Traits>, enable_if_t<is_std_char_type<CharT>::value>> + : string_caster<std::basic_string_view<CharT, Traits>, true> {}; +#endif + // Type caster for C-style strings. We basically use a std::string type caster, but also add the // ability to use None as a nullptr char* (which the string caster doesn't allow). template <typename CharT> struct type_caster<CharT, enable_if_t<is_std_char_type<CharT>::value>> { @@ -785,54 +1290,16 @@ public: } static PYBIND11_DESCR name() { return type_descr(_(PYBIND11_STRING_NAME)); } - template <typename _T> using cast_op_type = typename std::remove_reference<pybind11::detail::cast_op_type<_T>>::type; + template <typename _T> using cast_op_type = remove_reference_t<pybind11::detail::cast_op_type<_T>>; }; -template <typename T1, typename T2> class type_caster<std::pair<T1, T2>> { - typedef std::pair<T1, T2> type; +// Base implementation for std::tuple and std::pair +template <template<typename...> class Tuple, typename... Ts> class tuple_caster { + using type = Tuple<Ts...>; + static constexpr auto size = sizeof...(Ts); + using indices = make_index_sequence<size>; public: - bool load(handle src, bool convert) { - if (!isinstance<sequence>(src)) - return false; - const auto seq = reinterpret_borrow<sequence>(src); - if (seq.size() != 2) - return false; - return first.load(seq[0], convert) && second.load(seq[1], convert); - } - static handle cast(const type &src, return_value_policy policy, handle parent) { - auto o1 = reinterpret_steal<object>(make_caster<T1>::cast(src.first, policy, parent)); - auto o2 = reinterpret_steal<object>(make_caster<T2>::cast(src.second, policy, parent)); - if (!o1 || !o2) - return handle(); - tuple result(2); - PyTuple_SET_ITEM(result.ptr(), 0, o1.release().ptr()); - PyTuple_SET_ITEM(result.ptr(), 1, o2.release().ptr()); - return result.release(); - } - - static PYBIND11_DESCR name() { - return type_descr( - _("Tuple[") + make_caster<T1>::name() + _(", ") + make_caster<T2>::name() + _("]") - ); - } - - template <typename T> using cast_op_type = type; - - operator type() { - return type(cast_op<T1>(first), cast_op<T2>(second)); - } -protected: - make_caster<T1> first; - make_caster<T2> second; -}; - -template <typename... Tuple> class type_caster<std::tuple<Tuple...>> { - using type = std::tuple<Tuple...>; - using indices = make_index_sequence<sizeof...(Tuple)>; - static constexpr auto size = sizeof...(Tuple); - -public: bool load(handle src, bool convert) { if (!isinstance<sequence>(src)) return false; @@ -842,40 +1309,41 @@ public: return load_impl(seq, convert, indices{}); } - static handle cast(const type &src, return_value_policy policy, handle parent) { - return cast_impl(src, policy, parent, indices{}); + template <typename T> + static handle cast(T &&src, return_value_policy policy, handle parent) { + return cast_impl(std::forward<T>(src), policy, parent, indices{}); } static PYBIND11_DESCR name() { - return type_descr(_("Tuple[") + detail::concat(make_caster<Tuple>::name()...) + _("]")); + return type_descr(_("Tuple[") + detail::concat(make_caster<Ts>::name()...) + _("]")); } template <typename T> using cast_op_type = type; - operator type() { return implicit_cast(indices{}); } + operator type() & { return implicit_cast(indices{}); } + operator type() && { return std::move(*this).implicit_cast(indices{}); } protected: template <size_t... Is> - type implicit_cast(index_sequence<Is...>) { return type(cast_op<Tuple>(std::get<Is>(value))...); } + type implicit_cast(index_sequence<Is...>) & { return type(cast_op<Ts>(std::get<Is>(subcasters))...); } + template <size_t... Is> + type implicit_cast(index_sequence<Is...>) && { return type(cast_op<Ts>(std::move(std::get<Is>(subcasters)))...); } static constexpr bool load_impl(const sequence &, bool, index_sequence<>) { return true; } template <size_t... Is> bool load_impl(const sequence &seq, bool convert, index_sequence<Is...>) { - for (bool r : {std::get<Is>(value).load(seq[Is], convert)...}) + for (bool r : {std::get<Is>(subcasters).load(seq[Is], convert)...}) if (!r) return false; return true; } - static handle cast_impl(const type &, return_value_policy, handle, - index_sequence<>) { return tuple().release(); } - /* Implementation: Convert a C++ tuple into a Python tuple */ - template <size_t... Is> - static handle cast_impl(const type &src, return_value_policy policy, handle parent, index_sequence<Is...>) { - std::array<object, size> entries {{ - reinterpret_steal<object>(make_caster<Tuple>::cast(std::get<Is>(src), policy, parent))... + template <typename T, size_t... Is> + static handle cast_impl(T &&src, return_value_policy policy, handle parent, index_sequence<Is...>) { + std::array<object, size> entries{{ + reinterpret_steal<object>(make_caster<Ts>::cast(std::get<Is>(std::forward<T>(src)), policy, parent))... }}; for (const auto &entry: entries) if (!entry) @@ -887,9 +1355,15 @@ protected: return result.release(); } - std::tuple<make_caster<Tuple>...> value; + Tuple<make_caster<Ts>...> subcasters; }; +template <typename T1, typename T2> class type_caster<std::pair<T1, T2>> + : public tuple_caster<std::pair, T1, T2> {}; + +template <typename... Ts> class type_caster<std::tuple<Ts...>> + : public tuple_caster<std::tuple, Ts...> {}; + /// Helper class which abstracts away certain actions. Users can provide specializations for /// custom holders, but it's only necessary if the type has a non-standard interface. template <typename T> @@ -902,68 +1376,45 @@ template <typename type, typename holder_type> struct copyable_holder_caster : public type_caster_base<type> { public: using base = type_caster_base<type>; + static_assert(std::is_base_of<base, type_caster<type>>::value, + "Holder classes are only supported for custom types"); using base::base; using base::cast; using base::typeinfo; using base::value; - using base::temp; - PYBIND11_NOINLINE bool load(handle src, bool convert) { - return load(src, convert, Py_TYPE(src.ptr())); + bool load(handle src, bool convert) { + return base::template load_impl<copyable_holder_caster<type, holder_type>>(src, convert); } - bool load(handle src, bool convert, PyTypeObject *tobj) { - if (!src || !typeinfo) - return false; - if (src.is_none()) { - value = nullptr; - return true; - } - - if (typeinfo->default_holder) - throw cast_error("Unable to load a custom holder type from a default-holder instance"); - - if (typeinfo->simple_type) { /* Case 1: no multiple inheritance etc. involved */ - /* Check if we can safely perform a reinterpret-style cast */ - if (PyType_IsSubtype(tobj, typeinfo->type)) - return load_value_and_holder(src); - } else { /* Case 2: multiple inheritance */ - /* Check if we can safely perform a reinterpret-style cast */ - if (tobj == typeinfo->type) - return load_value_and_holder(src); - - /* If this is a python class, also check the parents recursively */ - auto const &type_dict = get_internals().registered_types_py; - bool new_style_class = PyType_Check((PyObject *) tobj); - if (type_dict.find(tobj) == type_dict.end() && new_style_class && tobj->tp_bases) { - auto parents = reinterpret_borrow<tuple>(tobj->tp_bases); - for (handle parent : parents) { - bool result = load(src, convert, (PyTypeObject *) parent.ptr()); - if (result) - return true; - } - } + explicit operator type*() { return this->value; } + explicit operator type&() { return *(this->value); } + explicit operator holder_type*() { return &holder; } - if (try_implicit_casts(src, convert)) - return true; - } + // Workaround for Intel compiler bug + // see pybind11 issue 94 + #if defined(__ICC) || defined(__INTEL_COMPILER) + operator holder_type&() { return holder; } + #else + explicit operator holder_type&() { return holder; } + #endif - if (convert) { - for (auto &converter : typeinfo->implicit_conversions) { - temp = reinterpret_steal<object>(converter(src.ptr(), typeinfo->type)); - if (load(temp, false)) - return true; - } - } + static handle cast(const holder_type &src, return_value_policy, handle) { + const auto *ptr = holder_helper<holder_type>::get(src); + return type_caster_base<type>::cast_holder(ptr, &src); + } - return false; +protected: + friend class type_caster_generic; + void check_holder_compat() { + if (typeinfo->default_holder) + throw cast_error("Unable to load a custom holder type from a default-holder instance"); } - bool load_value_and_holder(handle src) { - auto inst = (instance<type, holder_type> *) src.ptr(); - value = (void *) inst->value; - if (inst->holder_constructed) { - holder = inst->holder; + bool load_value(value_and_holder &&v_h) { + if (v_h.holder_constructed()) { + value = v_h.value_ptr(); + holder = v_h.holder<holder_type>(); return true; } else { throw cast_error("Unable to cast from non-held to held instance (T& to Holder<T>) " @@ -991,24 +1442,9 @@ public: return false; } - explicit operator type*() { return this->value; } - explicit operator type&() { return *(this->value); } - explicit operator holder_type*() { return &holder; } - - // Workaround for Intel compiler bug - // see pybind11 issue 94 - #if defined(__ICC) || defined(__INTEL_COMPILER) - operator holder_type&() { return holder; } - #else - explicit operator holder_type&() { return holder; } - #endif + static bool try_direct_conversions(handle) { return false; } - static handle cast(const holder_type &src, return_value_policy, handle) { - const auto *ptr = holder_helper<holder_type>::get(src); - return type_caster_base<type>::cast_holder(ptr, &src); - } -protected: holder_type holder; }; @@ -1018,6 +1454,9 @@ class type_caster<std::shared_ptr<T>> : public copyable_holder_caster<T, std::sh template <typename type, typename holder_type> struct move_only_holder_caster { + static_assert(std::is_base_of<type_caster_base<type>, type_caster<type>>::value, + "Holder classes are only supported for custom types"); + static handle cast(holder_type &&src, return_value_policy, handle) { auto *ptr = holder_helper<holder_type>::get(src); return type_caster_base<type>::cast_holder(ptr, &src); @@ -1030,7 +1469,7 @@ class type_caster<std::unique_ptr<type, deleter>> : public move_only_holder_caster<type, std::unique_ptr<type, deleter>> { }; template <typename type, typename holder_type> -using type_caster_holder = conditional_t<std::is_copy_constructible<holder_type>::value, +using type_caster_holder = conditional_t<is_copy_constructible<holder_type>::value, copyable_holder_caster<type, holder_type>, move_only_holder_caster<type, holder_type>>; @@ -1095,7 +1534,7 @@ template <typename T> using move_is_plain_type = satisfies_none_of<T, template <typename T, typename SFINAE = void> struct move_always : std::false_type {}; template <typename T> struct move_always<T, enable_if_t<all_of< move_is_plain_type<T>, - negation<std::is_copy_constructible<T>>, + negation<is_copy_constructible<T>>, std::is_move_constructible<T>, std::is_same<decltype(std::declval<make_caster<T>>().operator T&()), T&> >::value>> : std::true_type {}; @@ -1246,18 +1685,19 @@ NAMESPACE_END(detail) template <return_value_policy policy = return_value_policy::automatic_reference, typename... Args> tuple make_tuple(Args&&... args_) { - const size_t size = sizeof...(Args); + constexpr size_t size = sizeof...(Args); std::array<object, size> args { { reinterpret_steal<object>(detail::make_caster<Args>::cast( std::forward<Args>(args_), policy, nullptr))... } }; - for (auto &arg_value : args) { - if (!arg_value) { + for (size_t i = 0; i < args.size(); i++) { + if (!args[i]) { #if defined(NDEBUG) throw cast_error("make_tuple(): unable to convert arguments to Python object (compile in debug mode for details)"); #else - throw cast_error("make_tuple(): unable to convert arguments of types '" + - (std::string) type_id<std::tuple<Args...>>() + "' to Python object"); + std::array<std::string, size> argtypes { {type_id<Args>()...} }; + throw cast_error("make_tuple(): unable to convert argument of type '" + + argtypes[i] + "' to Python object"); #endif } } @@ -1272,14 +1712,17 @@ template <return_value_policy policy = return_value_policy::automatic_reference, /// Annotation for arguments struct arg { /// Constructs an argument with the name of the argument; if null or omitted, this is a positional argument. - constexpr explicit arg(const char *name = nullptr) : name(name), flag_noconvert(false) { } + constexpr explicit arg(const char *name = nullptr) : name(name), flag_noconvert(false), flag_none(true) { } /// Assign a value to this argument template <typename T> arg_v operator=(T &&value) const; /// Indicate that the type should not be converted in the type caster arg &noconvert(bool flag = true) { flag_noconvert = flag; return *this; } + /// Indicates that the argument should/shouldn't allow None (e.g. for nullable pointer args) + arg &none(bool flag = true) { flag_none = flag; return *this; } const char *name; ///< If non-null, this is a named kwargs argument bool flag_noconvert : 1; ///< If set, do not allow conversion (requires a supporting type caster!) + bool flag_none : 1; ///< If set (the default), allow None to be passed to this argument }; /// \ingroup annotations @@ -1312,6 +1755,9 @@ public: /// Same as `arg::noconvert()`, but returns *this as arg_v&, not arg& arg_v &noconvert(bool flag = true) { arg::noconvert(flag); return *this; } + /// Same as `arg::nonone()`, but returns *this as arg_v&, not arg& + arg_v &none(bool flag = true) { arg::none(flag); return *this; } + /// The default value object value; /// The (optional) description of the default value @@ -1337,7 +1783,7 @@ constexpr arg operator"" _a(const char *name, size_t) { return arg(name); } NAMESPACE_BEGIN(detail) -// forward declaration +// forward declaration (definition in attr.h) struct function_record; /// Internal data associated with a single function call @@ -1355,6 +1801,9 @@ struct function_call { /// The parent, if any handle parent; + + /// If this is a call to an initializer, this argument contains `self` + handle init_self; }; @@ -1383,14 +1832,14 @@ public: return load_impl_sequence(call, indices{}); } - template <typename Return, typename Func> - enable_if_t<!std::is_void<Return>::value, Return> call(Func &&f) { - return call_impl<Return>(std::forward<Func>(f), indices{}); + template <typename Return, typename Guard, typename Func> + enable_if_t<!std::is_void<Return>::value, Return> call(Func &&f) && { + return std::move(*this).template call_impl<Return>(std::forward<Func>(f), indices{}, Guard{}); } - template <typename Return, typename Func> - enable_if_t<std::is_void<Return>::value, void_type> call(Func &&f) { - call_impl<Return>(std::forward<Func>(f), indices{}); + template <typename Return, typename Guard, typename Func> + enable_if_t<std::is_void<Return>::value, void_type> call(Func &&f) && { + std::move(*this).template call_impl<Return>(std::forward<Func>(f), indices{}, Guard{}); return void_type(); } @@ -1400,18 +1849,18 @@ private: template <size_t... Is> bool load_impl_sequence(function_call &call, index_sequence<Is...>) { - for (bool r : {std::get<Is>(value).load(call.args[Is], call.args_convert[Is])...}) + for (bool r : {std::get<Is>(argcasters).load(call.args[Is], call.args_convert[Is])...}) if (!r) return false; return true; } - template <typename Return, typename Func, size_t... Is> - Return call_impl(Func &&f, index_sequence<Is...>) { - return std::forward<Func>(f)(cast_op<Args>(std::get<Is>(value))...); + template <typename Return, typename Func, size_t... Is, typename Guard> + Return call_impl(Func &&f, index_sequence<Is...>, Guard &&) { + return std::forward<Func>(f)(cast_op<Args>(std::move(std::get<Is>(argcasters)))...); } - std::tuple<make_caster<Args>...> value; + std::tuple<make_caster<Args>...> argcasters; }; /// Helper class which collects only positional arguments for a Python function call. @@ -1601,4 +2050,4 @@ NAMESPACE_END(detail) template<> class type_caster<Type> : public type_caster_base<Type> { }; \ }} -NAMESPACE_END(pybind11) +NAMESPACE_END(PYBIND11_NAMESPACE) |