diff options
author | Jason Lowe-Power <jason@lowepower.com> | 2017-11-17 17:02:05 -0800 |
---|---|---|
committer | Jason Lowe-Power <jason@lowepower.com> | 2017-12-14 00:27:59 +0000 |
commit | f07d5069d86e31ecf195664850f79fb00c445bd3 (patch) | |
tree | f54ac06896fa828f873d199a0e9b25bd94911c79 /ext/pybind11/include | |
parent | 3f64b374c49491f18dc2ca538ed8c8597e4aac83 (diff) | |
download | gem5-f07d5069d86e31ecf195664850f79fb00c445bd3.tar.xz |
ext: Upgrade PyBind11 to version 2.2.1
This upgrade is necessary for pybind to build with GCC 7.2.
We still need to add the patch for stl.h. MSC_FULL_VER change is no longer
needed.
See https://gem5-review.googlesource.com/c/public/gem5/+/2230
Change-Id: I806729217d022070583994c2dfcaa74476aef30f
Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
Reviewed-on: https://gem5-review.googlesource.com/5801
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Diffstat (limited to 'ext/pybind11/include')
24 files changed, 4334 insertions, 1880 deletions
diff --git a/ext/pybind11/include/pybind11/attr.h b/ext/pybind11/include/pybind11/attr.h index e38a1a32d..dce875a6b 100644 --- a/ext/pybind11/include/pybind11/attr.h +++ b/ext/pybind11/include/pybind11/attr.h @@ -1,5 +1,5 @@ /* - pybind11/pybind11.h: Infrastructure for processing custom + pybind11/attr.h: Infrastructure for processing custom type and function attributes Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch> @@ -12,7 +12,7 @@ #include "cast.h" -NAMESPACE_BEGIN(pybind11) +NAMESPACE_BEGIN(PYBIND11_NAMESPACE) /// \addtogroup annotations /// @{ @@ -58,15 +58,56 @@ struct metaclass { handle value; PYBIND11_DEPRECATED("py::metaclass() is no longer required. It's turned on by default now.") - metaclass() = default; + metaclass() {} /// Override pybind11's default metaclass explicit metaclass(handle value) : value(value) { } }; +/// Annotation that marks a class as local to the module: +struct module_local { const bool value; constexpr module_local(bool v = true) : value(v) { } }; + /// Annotation to mark enums as an arithmetic type struct arithmetic { }; +/** \rst + A call policy which places one or more guard variables (``Ts...``) around the function call. + + For example, this definition: + + .. code-block:: cpp + + m.def("foo", foo, py::call_guard<T>()); + + is equivalent to the following pseudocode: + + .. code-block:: cpp + + m.def("foo", [](args...) { + T scope_guard; + return foo(args...); // forwarded arguments + }); + \endrst */ +template <typename... Ts> struct call_guard; + +template <> struct call_guard<> { using type = detail::void_type; }; + +template <typename T> +struct call_guard<T> { + static_assert(std::is_default_constructible<T>::value, + "The guard type must be default constructible"); + + using type = T; +}; + +template <typename T, typename... Ts> +struct call_guard<T, Ts...> { + struct type { + T guard{}; // Compose multiple guard types with left-to-right default-constructor order + typename call_guard<Ts...>::type next{}; + }; +}; + /// @} annotations NAMESPACE_BEGIN(detail) @@ -75,8 +116,6 @@ enum op_id : int; enum op_type : int; struct undefined_t; template <op_id id, op_type ot, typename L = undefined_t, typename R = undefined_t> struct op_; -template <typename... Args> struct init; -template <typename... Args> struct init_alias; inline void keep_alive_impl(size_t Nurse, size_t Patient, function_call &call, handle ret); /// Internal data structure which holds metadata about a keyword argument @@ -85,16 +124,17 @@ struct argument_record { const char *descr; ///< Human-readable version of the argument value handle value; ///< Associated Python object bool convert : 1; ///< True if the argument is allowed to convert when loading + bool none : 1; ///< True if None is allowed when loading - argument_record(const char *name, const char *descr, handle value, bool convert) - : name(name), descr(descr), value(value), convert(convert) { } + argument_record(const char *name, const char *descr, handle value, bool convert, bool none) + : name(name), descr(descr), value(value), convert(convert), none(none) { } }; /// Internal data structure which holds metadata about a bound function (signature, overloads, etc.) struct function_record { function_record() - : is_constructor(false), is_stateless(false), is_operator(false), - has_args(false), has_kwargs(false), is_method(false) { } + : is_constructor(false), is_new_style_constructor(false), is_stateless(false), + is_operator(false), has_args(false), has_kwargs(false), is_method(false) { } /// Function name char *name = nullptr; /* why no C++ strings? They generate heavier code.. */ @@ -123,6 +163,9 @@ struct function_record { /// True if name == '__init__' bool is_constructor : 1; + /// True if this is a new-style `__init__` defined in `detail/init.h` + bool is_new_style_constructor : 1; + /// True if this is a stateless function pointer bool is_stateless : 1; @@ -157,7 +200,7 @@ struct function_record { /// Special data structure which (temporarily) holds metadata about a bound class struct type_record { PYBIND11_NOINLINE type_record() - : multiple_inheritance(false), dynamic_attr(false), buffer_protocol(false) { } + : multiple_inheritance(false), dynamic_attr(false), buffer_protocol(false), module_local(false) { } /// Handle to the parent scope handle scope; @@ -171,17 +214,17 @@ struct type_record { /// How large is the underlying C++ type? size_t type_size = 0; - /// How large is pybind11::instance<type>? - size_t instance_size = 0; + /// How large is the type's holder? + size_t holder_size = 0; /// The global operator new can be overridden with a class-specific variant void *(*operator_new)(size_t) = ::operator new; - /// Function pointer to class_<..>::init_holder - void (*init_holder)(PyObject *, const void *) = nullptr; + /// Function pointer to class_<..>::init_instance + void (*init_instance)(instance *, const void *) = nullptr; /// Function pointer to class_<..>::dealloc - void (*dealloc)(PyObject *) = nullptr; + void (*dealloc)(detail::value_and_holder &) = nullptr; /// List of base classes of the newly created type list bases; @@ -204,17 +247,20 @@ struct type_record { /// Is the default (unique_ptr) holder type used? bool default_holder : 1; - PYBIND11_NOINLINE void add_base(const std::type_info *base, void *(*caster)(void *)) { - auto base_info = detail::get_type_info(*base, false); + /// Is the class definition local to the module shared object? + bool module_local : 1; + + PYBIND11_NOINLINE void add_base(const std::type_info &base, void *(*caster)(void *)) { + auto base_info = detail::get_type_info(base, false); if (!base_info) { - std::string tname(base->name()); + std::string tname(base.name()); detail::clean_type_id(tname); pybind11_fail("generic_type: type \"" + std::string(name) + "\" referenced unknown base type \"" + tname + "\""); } if (default_holder != base_info->default_holder) { - std::string tname(base->name()); + std::string tname(base.name()); detail::clean_type_id(tname); pybind11_fail("generic_type: type \"" + std::string(name) + "\" " + (default_holder ? "does not have" : "has") + @@ -228,7 +274,7 @@ struct type_record { dynamic_attr = true; if (caster) - base_info->implicit_casts.push_back(std::make_pair(type, caster)); + base_info->implicit_casts.emplace_back(type, caster); } }; @@ -238,6 +284,9 @@ inline function_call::function_call(function_record &f, handle p) : args_convert.reserve(f.nargs); } +/// Tag for a new-style `__init__` defined in `detail/init.h` +struct is_new_style_constructor { }; + /** * Partial template specializations to process custom attributes provided to * cpp_function_ and class_. These are either used to initialize the respective @@ -296,12 +345,16 @@ template <> struct process_attribute<is_operator> : process_attribute_default<is static void init(const is_operator &, function_record *r) { r->is_operator = true; } }; +template <> struct process_attribute<is_new_style_constructor> : process_attribute_default<is_new_style_constructor> { + static void init(const is_new_style_constructor &, function_record *r) { r->is_new_style_constructor = true; } +}; + /// Process a keyword argument attribute (*without* a default value) template <> struct process_attribute<arg> : process_attribute_default<arg> { static void init(const arg &a, function_record *r) { if (r->is_method && r->args.empty()) - r->args.emplace_back("self", nullptr, handle(), true /*convert*/); - r->args.emplace_back(a.name, nullptr, handle(), !a.flag_noconvert); + r->args.emplace_back("self", nullptr, handle(), true /*convert*/, false /*none not allowed*/); + r->args.emplace_back(a.name, nullptr, handle(), !a.flag_noconvert, a.flag_none); } }; @@ -309,7 +362,7 @@ template <> struct process_attribute<arg> : process_attribute_default<arg> { template <> struct process_attribute<arg_v> : process_attribute_default<arg_v> { static void init(const arg_v &a, function_record *r) { if (r->is_method && r->args.empty()) - r->args.emplace_back("self", nullptr /*descr*/, handle() /*parent*/, true /*convert*/); + r->args.emplace_back("self", nullptr /*descr*/, handle() /*parent*/, true /*convert*/, false /*none not allowed*/); if (!a.value) { #if !defined(NDEBUG) @@ -332,7 +385,7 @@ template <> struct process_attribute<arg_v> : process_attribute_default<arg_v> { "Compile in debug mode for more information."); #endif } - r->args.emplace_back(a.name, a.descr, a.value.inc_ref(), !a.flag_noconvert); + r->args.emplace_back(a.name, a.descr, a.value.inc_ref(), !a.flag_noconvert, a.flag_none); } }; @@ -345,7 +398,7 @@ struct process_attribute<T, enable_if_t<is_pyobject<T>::value>> : process_attrib /// Process a parent class attribute (deprecated, does not support multiple inheritance) template <typename T> struct process_attribute<base<T>> : process_attribute_default<base<T>> { - static void init(const base<T> &, type_record *r) { r->add_base(&typeid(T), nullptr); } + static void init(const base<T> &, type_record *r) { r->add_base(typeid(T), nullptr); } }; /// Process a multiple inheritance attribute @@ -369,12 +422,19 @@ struct process_attribute<metaclass> : process_attribute_default<metaclass> { static void init(const metaclass &m, type_record *r) { r->metaclass = m.value; } }; +template <> +struct process_attribute<module_local> : process_attribute_default<module_local> { + static void init(const module_local &l, type_record *r) { r->module_local = l.value; } +}; /// Process an 'arithmetic' attribute for enums (does nothing here) template <> struct process_attribute<arithmetic> : process_attribute_default<arithmetic> {}; -/*** +template <typename... Ts> +struct process_attribute<call_guard<Ts...>> : process_attribute_default<call_guard<Ts...>> { }; + +/** * Process a keep_alive call policy -- invokes keep_alive_impl during the * pre-call handler if both Nurse, Patient != 0 and use the post-call handler * otherwise @@ -410,6 +470,13 @@ template <typename... Args> struct process_attributes { } }; +template <typename T> +using is_call_guard = is_instantiation<call_guard, T>; + +/// Extract the ``type`` from the first `call_guard` in `Extras...` (or `void_type` if none found) +template <typename... Extra> +using extract_guard_t = typename exactly_one_t<is_call_guard, call_guard<>, Extra...>::type; + /// Check the number of named arguments at compile time template <typename... Extra, size_t named = constexpr_sum(std::is_base_of<arg, Extra>::value...), @@ -419,4 +486,4 @@ constexpr bool expected_num_args(size_t nargs, bool has_args, bool has_kwargs) { } NAMESPACE_END(detail) -NAMESPACE_END(pybind11) +NAMESPACE_END(PYBIND11_NAMESPACE) diff --git a/ext/pybind11/include/pybind11/buffer_info.h b/ext/pybind11/include/pybind11/buffer_info.h new file mode 100644 index 000000000..9f072fa73 --- /dev/null +++ b/ext/pybind11/include/pybind11/buffer_info.h @@ -0,0 +1,108 @@ +/* + pybind11/buffer_info.h: Python buffer object interface + + Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch> + + All rights reserved. Use of this source code is governed by a + BSD-style license that can be found in the LICENSE file. +*/ + +#pragma once + +#include "detail/common.h" + +NAMESPACE_BEGIN(PYBIND11_NAMESPACE) + +/// Information record describing a Python buffer object +struct buffer_info { + void *ptr = nullptr; // Pointer to the underlying storage + ssize_t itemsize = 0; // Size of individual items in bytes + ssize_t size = 0; // Total number of entries + std::string format; // For homogeneous buffers, this should be set to format_descriptor<T>::format() + ssize_t ndim = 0; // Number of dimensions + std::vector<ssize_t> shape; // Shape of the tensor (1 entry per dimension) + std::vector<ssize_t> strides; // Number of entries between adjacent entries (for each per dimension) + + buffer_info() { } + + buffer_info(void *ptr, ssize_t itemsize, const std::string &format, ssize_t ndim, + detail::any_container<ssize_t> shape_in, detail::any_container<ssize_t> strides_in) + : ptr(ptr), itemsize(itemsize), size(1), format(format), ndim(ndim), + shape(std::move(shape_in)), strides(std::move(strides_in)) { + if (ndim != (ssize_t) shape.size() || ndim != (ssize_t) strides.size()) + pybind11_fail("buffer_info: ndim doesn't match shape and/or strides length"); + for (size_t i = 0; i < (size_t) ndim; ++i) + size *= shape[i]; + } + + template <typename T> + buffer_info(T *ptr, detail::any_container<ssize_t> shape_in, detail::any_container<ssize_t> strides_in) + : buffer_info(private_ctr_tag(), ptr, sizeof(T), format_descriptor<T>::format(), static_cast<ssize_t>(shape_in->size()), std::move(shape_in), std::move(strides_in)) { } + + buffer_info(void *ptr, ssize_t itemsize, const std::string &format, ssize_t size) + : buffer_info(ptr, itemsize, format, 1, {size}, {itemsize}) { } + + template <typename T> + buffer_info(T *ptr, ssize_t size) + : buffer_info(ptr, sizeof(T), format_descriptor<T>::format(), size) { } + + explicit buffer_info(Py_buffer *view, bool ownview = true) + : buffer_info(view->buf, view->itemsize, view->format, view->ndim, + {view->shape, view->shape + view->ndim}, {view->strides, view->strides + view->ndim}) { + this->view = view; + this->ownview = ownview; + } + + buffer_info(const buffer_info &) = delete; + buffer_info& operator=(const buffer_info &) = delete; + + buffer_info(buffer_info &&other) { + (*this) = std::move(other); + } + + buffer_info& operator=(buffer_info &&rhs) { + ptr = rhs.ptr; + itemsize = rhs.itemsize; + size = rhs.size; + format = std::move(rhs.format); + ndim = rhs.ndim; + shape = std::move(rhs.shape); + strides = std::move(rhs.strides); + std::swap(view, rhs.view); + std::swap(ownview, rhs.ownview); + return *this; + } + + ~buffer_info() { + if (view && ownview) { PyBuffer_Release(view); delete view; } + } + +private: + struct private_ctr_tag { }; + + buffer_info(private_ctr_tag, void *ptr, ssize_t itemsize, const std::string &format, ssize_t ndim, + detail::any_container<ssize_t> &&shape_in, detail::any_container<ssize_t> &&strides_in) + : buffer_info(ptr, itemsize, format, ndim, std::move(shape_in), std::move(strides_in)) { } + + Py_buffer *view = nullptr; + bool ownview = false; +}; + +NAMESPACE_BEGIN(detail) + +template <typename T, typename SFINAE = void> struct compare_buffer_info { + static bool compare(const buffer_info& b) { + return b.format == format_descriptor<T>::format() && b.itemsize == (ssize_t) sizeof(T); + } +}; + +template <typename T> struct compare_buffer_info<T, detail::enable_if_t<std::is_integral<T>::value>> { + static bool compare(const buffer_info& b) { + return (size_t) b.itemsize == sizeof(T) && (b.format == format_descriptor<T>::value || + ((sizeof(T) == sizeof(long)) && b.format == (std::is_unsigned<T>::value ? "L" : "l")) || + ((sizeof(T) == sizeof(size_t)) && b.format == (std::is_unsigned<T>::value ? "N" : "n"))); + } +}; + +NAMESPACE_END(detail) +NAMESPACE_END(PYBIND11_NAMESPACE) 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) diff --git a/ext/pybind11/include/pybind11/chrono.h b/ext/pybind11/include/pybind11/chrono.h index 8a41d08b0..95ada76e0 100644 --- a/ext/pybind11/include/pybind11/chrono.h +++ b/ext/pybind11/include/pybind11/chrono.h @@ -27,7 +27,7 @@ #define PyDateTime_DELTA_GET_MICROSECONDS(o) (((PyDateTime_Delta*)o)->microseconds) #endif -NAMESPACE_BEGIN(pybind11) +NAMESPACE_BEGIN(PYBIND11_NAMESPACE) NAMESPACE_BEGIN(detail) template <typename type> class duration_caster { @@ -159,4 +159,4 @@ template <typename Rep, typename Period> class type_caster<std::chrono::duration }; NAMESPACE_END(detail) -NAMESPACE_END(pybind11) +NAMESPACE_END(PYBIND11_NAMESPACE) diff --git a/ext/pybind11/include/pybind11/common.h b/ext/pybind11/include/pybind11/common.h index ac2be7aef..6c8a4f1e8 100644 --- a/ext/pybind11/include/pybind11/common.h +++ b/ext/pybind11/include/pybind11/common.h @@ -1,719 +1,2 @@ -/* - pybind11/common.h -- Basic macros - - Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch> - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#pragma once - -#if !defined(NAMESPACE_BEGIN) -# define NAMESPACE_BEGIN(name) namespace name { -#endif -#if !defined(NAMESPACE_END) -# define NAMESPACE_END(name) } -#endif - -// Neither MSVC nor Intel support enough of C++14 yet (in particular, as of MSVC 2015 and ICC 17 -// beta, neither support extended constexpr, which we rely on in descr.h), so don't enable pybind -// CPP14 features for them. -#if !defined(_MSC_VER) && !defined(__INTEL_COMPILER) -# if __cplusplus >= 201402L -# define PYBIND11_CPP14 -# if __cplusplus > 201402L /* Temporary: should be updated to >= the final C++17 value once known */ -# define PYBIND11_CPP17 -# endif -# endif -#endif - -// Compiler version assertions -#if defined(__INTEL_COMPILER) -# if __INTEL_COMPILER < 1500 -# error pybind11 requires Intel C++ compiler v15 or newer -# endif -#elif defined(__clang__) && !defined(__apple_build_version__) -# if __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 3) -# error pybind11 requires clang 3.3 or newer -# endif -#elif defined(__clang__) -// Apple changes clang version macros to its Xcode version; the first Xcode release based on -// (upstream) clang 3.3 was Xcode 5: -# if __clang_major__ < 5 -# error pybind11 requires Xcode/clang 5.0 or newer -# endif -#elif defined(__GNUG__) -# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8) -# error pybind11 requires gcc 4.8 or newer -# endif -#elif defined(_MSC_VER) -// Pybind hits various compiler bugs in 2015u2 and earlier, and also makes use of some stl features -// (e.g. std::negation) added in 2015u3: -# if _MSC_FULL_VER < 190024210 -# error pybind11 requires MSVC 2015 update 3 or newer -# endif -#endif - -#if !defined(PYBIND11_EXPORT) -# if defined(WIN32) || defined(_WIN32) -# define PYBIND11_EXPORT __declspec(dllexport) -# else -# define PYBIND11_EXPORT __attribute__ ((visibility("default"))) -# endif -#endif - -#if defined(_MSC_VER) -# define PYBIND11_NOINLINE __declspec(noinline) -#else -# define PYBIND11_NOINLINE __attribute__ ((noinline)) -#endif - -#if defined(PYBIND11_CPP14) -# define PYBIND11_DEPRECATED(reason) [[deprecated(reason)]] -#elif defined(__clang__) -# define PYBIND11_DEPRECATED(reason) __attribute__((deprecated(reason))) -#elif defined(__GNUG__) -# define PYBIND11_DEPRECATED(reason) __attribute__((deprecated)) -#elif defined(_MSC_VER) -# define PYBIND11_DEPRECATED(reason) __declspec(deprecated) -#endif - -#define PYBIND11_VERSION_MAJOR 2 -#define PYBIND11_VERSION_MINOR 1 -#define PYBIND11_VERSION_PATCH 1 - -/// Include Python header, disable linking to pythonX_d.lib on Windows in debug mode -#if defined(_MSC_VER) -# if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 4) -# define HAVE_ROUND 1 -# endif -# pragma warning(push) -# pragma warning(disable: 4510 4610 4512 4005) -# if defined(_DEBUG) -# define PYBIND11_DEBUG_MARKER -# undef _DEBUG -# endif -#endif - -#include <Python.h> -#include <frameobject.h> -#include <pythread.h> - -#if defined(_WIN32) && (defined(min) || defined(max)) -# error Macro clash with min and max -- define NOMINMAX when compiling your program on Windows -#endif - -#if defined(isalnum) -# undef isalnum -# undef isalpha -# undef islower -# undef isspace -# undef isupper -# undef tolower -# undef toupper -#endif - -#if defined(_MSC_VER) -# if defined(PYBIND11_DEBUG_MARKER) -# define _DEBUG -# undef PYBIND11_DEBUG_MARKER -# endif -# pragma warning(pop) -#endif - -#include <cstddef> -#include <forward_list> -#include <vector> -#include <string> -#include <stdexcept> -#include <unordered_set> -#include <unordered_map> -#include <memory> -#include <typeindex> -#include <type_traits> - -#if PY_MAJOR_VERSION >= 3 /// Compatibility macros for various Python versions -#define PYBIND11_INSTANCE_METHOD_NEW(ptr, class_) PyInstanceMethod_New(ptr) -#define PYBIND11_BYTES_CHECK PyBytes_Check -#define PYBIND11_BYTES_FROM_STRING PyBytes_FromString -#define PYBIND11_BYTES_FROM_STRING_AND_SIZE PyBytes_FromStringAndSize -#define PYBIND11_BYTES_AS_STRING_AND_SIZE PyBytes_AsStringAndSize -#define PYBIND11_BYTES_AS_STRING PyBytes_AsString -#define PYBIND11_BYTES_SIZE PyBytes_Size -#define PYBIND11_LONG_CHECK(o) PyLong_Check(o) -#define PYBIND11_LONG_AS_LONGLONG(o) PyLong_AsLongLong(o) -#define PYBIND11_LONG_AS_UNSIGNED_LONGLONG(o) PyLong_AsUnsignedLongLong(o) -#define PYBIND11_BYTES_NAME "bytes" -#define PYBIND11_STRING_NAME "str" -#define PYBIND11_SLICE_OBJECT PyObject -#define PYBIND11_FROM_STRING PyUnicode_FromString -#define PYBIND11_STR_TYPE ::pybind11::str -#define PYBIND11_PLUGIN_IMPL(name) \ - extern "C" PYBIND11_EXPORT PyObject *PyInit_##name() -#else -#define PYBIND11_INSTANCE_METHOD_NEW(ptr, class_) PyMethod_New(ptr, nullptr, class_) -#define PYBIND11_BYTES_CHECK PyString_Check -#define PYBIND11_BYTES_FROM_STRING PyString_FromString -#define PYBIND11_BYTES_FROM_STRING_AND_SIZE PyString_FromStringAndSize -#define PYBIND11_BYTES_AS_STRING_AND_SIZE PyString_AsStringAndSize -#define PYBIND11_BYTES_AS_STRING PyString_AsString -#define PYBIND11_BYTES_SIZE PyString_Size -#define PYBIND11_LONG_CHECK(o) (PyInt_Check(o) || PyLong_Check(o)) -#define PYBIND11_LONG_AS_LONGLONG(o) (PyInt_Check(o) ? (long long) PyLong_AsLong(o) : PyLong_AsLongLong(o)) -#define PYBIND11_LONG_AS_UNSIGNED_LONGLONG(o) (PyInt_Check(o) ? (unsigned long long) PyLong_AsUnsignedLong(o) : PyLong_AsUnsignedLongLong(o)) -#define PYBIND11_BYTES_NAME "str" -#define PYBIND11_STRING_NAME "unicode" -#define PYBIND11_SLICE_OBJECT PySliceObject -#define PYBIND11_FROM_STRING PyString_FromString -#define PYBIND11_STR_TYPE ::pybind11::bytes -#define PYBIND11_PLUGIN_IMPL(name) \ - static PyObject *pybind11_init_wrapper(); \ - extern "C" PYBIND11_EXPORT void init##name() { \ - (void)pybind11_init_wrapper(); \ - } \ - PyObject *pybind11_init_wrapper() -#endif - -#if PY_VERSION_HEX >= 0x03050000 && PY_VERSION_HEX < 0x03050200 -extern "C" { - struct _Py_atomic_address { void *value; }; - PyAPI_DATA(_Py_atomic_address) _PyThreadState_Current; -} -#endif - -#define PYBIND11_TRY_NEXT_OVERLOAD ((PyObject *) 1) // special failure return code -#define PYBIND11_STRINGIFY(x) #x -#define PYBIND11_TOSTRING(x) PYBIND11_STRINGIFY(x) -#define PYBIND11_INTERNALS_ID "__pybind11_" \ - PYBIND11_TOSTRING(PYBIND11_VERSION_MAJOR) "_" PYBIND11_TOSTRING(PYBIND11_VERSION_MINOR) "__" - -/** \rst - This macro creates the entry point that will be invoked when the Python interpreter - imports a plugin library. Please create a `module` in the function body and return - the pointer to its underlying Python object at the end. - - .. code-block:: cpp - - PYBIND11_PLUGIN(example) { - pybind11::module m("example", "pybind11 example plugin"); - /// Set up bindings here - return m.ptr(); - } -\endrst */ -#define PYBIND11_PLUGIN(name) \ - static PyObject *pybind11_init(); \ - PYBIND11_PLUGIN_IMPL(name) { \ - int major, minor; \ - if (sscanf(Py_GetVersion(), "%i.%i", &major, &minor) != 2) { \ - PyErr_SetString(PyExc_ImportError, "Can't parse Python version."); \ - return nullptr; \ - } else if (major != PY_MAJOR_VERSION || minor != PY_MINOR_VERSION) { \ - PyErr_Format(PyExc_ImportError, \ - "Python version mismatch: module was compiled for " \ - "version %i.%i, while the interpreter is running " \ - "version %i.%i.", PY_MAJOR_VERSION, PY_MINOR_VERSION, \ - major, minor); \ - return nullptr; \ - } \ - try { \ - return pybind11_init(); \ - } catch (pybind11::error_already_set &e) { \ - e.clear(); \ - PyErr_SetString(PyExc_ImportError, e.what()); \ - return nullptr; \ - } catch (const std::exception &e) { \ - PyErr_SetString(PyExc_ImportError, e.what()); \ - return nullptr; \ - } \ - } \ - PyObject *pybind11_init() - -NAMESPACE_BEGIN(pybind11) - -using ssize_t = Py_ssize_t; -using size_t = std::size_t; - -/// Approach used to cast a previously unknown C++ instance into a Python object -enum class return_value_policy : uint8_t { - /** This is the default return value policy, which falls back to the policy - return_value_policy::take_ownership when the return value is a pointer. - Otherwise, it uses return_value::move or return_value::copy for rvalue - and lvalue references, respectively. See below for a description of what - all of these different policies do. */ - automatic = 0, - - /** As above, but use policy return_value_policy::reference when the return - value is a pointer. This is the default conversion policy for function - arguments when calling Python functions manually from C++ code (i.e. via - handle::operator()). You probably won't need to use this. */ - automatic_reference, - - /** Reference an existing object (i.e. do not create a new copy) and take - ownership. Python will call the destructor and delete operator when the - object’s reference count reaches zero. Undefined behavior ensues when - the C++ side does the same.. */ - take_ownership, - - /** Create a new copy of the returned object, which will be owned by - Python. This policy is comparably safe because the lifetimes of the two - instances are decoupled. */ - copy, - - /** Use std::move to move the return value contents into a new instance - that will be owned by Python. This policy is comparably safe because the - lifetimes of the two instances (move source and destination) are - decoupled. */ - move, - - /** Reference an existing object, but do not take ownership. The C++ side - is responsible for managing the object’s lifetime and deallocating it - when it is no longer used. Warning: undefined behavior will ensue when - the C++ side deletes an object that is still referenced and used by - Python. */ - reference, - - /** This policy only applies to methods and properties. It references the - object without taking ownership similar to the above - return_value_policy::reference policy. In contrast to that policy, the - function or property’s implicit this argument (called the parent) is - considered to be the the owner of the return value (the child). - pybind11 then couples the lifetime of the parent to the child via a - reference relationship that ensures that the parent cannot be garbage - collected while Python is still using the child. More advanced - variations of this scheme are also possible using combinations of - return_value_policy::reference and the keep_alive call policy */ - reference_internal -}; - -/// Information record describing a Python buffer object -struct buffer_info { - void *ptr = nullptr; // Pointer to the underlying storage - size_t itemsize = 0; // Size of individual items in bytes - size_t size = 0; // Total number of entries - std::string format; // For homogeneous buffers, this should be set to format_descriptor<T>::format() - size_t ndim = 0; // Number of dimensions - std::vector<size_t> shape; // Shape of the tensor (1 entry per dimension) - std::vector<size_t> strides; // Number of entries between adjacent entries (for each per dimension) - - buffer_info() { } - - buffer_info(void *ptr, size_t itemsize, const std::string &format, size_t ndim, - const std::vector<size_t> &shape, const std::vector<size_t> &strides) - : ptr(ptr), itemsize(itemsize), size(1), format(format), - ndim(ndim), shape(shape), strides(strides) { - for (size_t i = 0; i < ndim; ++i) - size *= shape[i]; - } - - buffer_info(void *ptr, size_t itemsize, const std::string &format, size_t size) - : buffer_info(ptr, itemsize, format, 1, std::vector<size_t> { size }, - std::vector<size_t> { itemsize }) { } - - explicit buffer_info(Py_buffer *view, bool ownview = true) - : ptr(view->buf), itemsize((size_t) view->itemsize), size(1), format(view->format), - ndim((size_t) view->ndim), shape((size_t) view->ndim), strides((size_t) view->ndim), view(view), ownview(ownview) { - for (size_t i = 0; i < (size_t) view->ndim; ++i) { - shape[i] = (size_t) view->shape[i]; - strides[i] = (size_t) view->strides[i]; - size *= shape[i]; - } - } - - buffer_info(const buffer_info &) = delete; - buffer_info& operator=(const buffer_info &) = delete; - - buffer_info(buffer_info &&other) { - (*this) = std::move(other); - } - - buffer_info& operator=(buffer_info &&rhs) { - ptr = rhs.ptr; - itemsize = rhs.itemsize; - size = rhs.size; - format = std::move(rhs.format); - ndim = rhs.ndim; - shape = std::move(rhs.shape); - strides = std::move(rhs.strides); - std::swap(view, rhs.view); - std::swap(ownview, rhs.ownview); - return *this; - } - - ~buffer_info() { - if (view && ownview) { PyBuffer_Release(view); delete view; } - } - -private: - Py_buffer *view = nullptr; - bool ownview = false; -}; - -NAMESPACE_BEGIN(detail) - -inline static constexpr int log2(size_t n, int k = 0) { return (n <= 1) ? k : log2(n >> 1, k + 1); } - -inline std::string error_string(); - -/// Core part of the 'instance' type which POD (needed to be able to use 'offsetof') -template <typename type> struct instance_essentials { - PyObject_HEAD - type *value; - PyObject *weakrefs; - bool owned : 1; - bool holder_constructed : 1; -}; - -/// PyObject wrapper around generic types, includes a special holder type that is responsible for lifetime management -template <typename type, typename holder_type = std::unique_ptr<type>> struct instance : instance_essentials<type> { - holder_type holder; -}; - -struct overload_hash { - inline size_t operator()(const std::pair<const PyObject *, const char *>& v) const { - size_t value = std::hash<const void *>()(v.first); - value ^= std::hash<const void *>()(v.second) + 0x9e3779b9 + (value<<6) + (value>>2); - return value; - } -}; - -/// Internal data structure used to track registered instances and types -struct internals { - std::unordered_map<std::type_index, void*> registered_types_cpp; // std::type_index -> type_info - std::unordered_map<const void *, void*> registered_types_py; // PyTypeObject* -> type_info - std::unordered_multimap<const void *, void*> registered_instances; // void * -> PyObject* - std::unordered_set<std::pair<const PyObject *, const char *>, overload_hash> inactive_overload_cache; - std::unordered_map<std::type_index, std::vector<bool (*)(PyObject *, void *&)>> direct_conversions; - std::forward_list<void (*) (std::exception_ptr)> registered_exception_translators; - std::unordered_map<std::string, void *> shared_data; // Custom data to be shared across extensions - PyTypeObject *static_property_type; - PyTypeObject *default_metaclass; - std::unordered_map<size_t, PyObject *> bases; // one base type per `instance_size` (very few) -#if defined(WITH_THREAD) - decltype(PyThread_create_key()) tstate = 0; // Usually an int but a long on Cygwin64 with Python 3.x - PyInterpreterState *istate = nullptr; -#endif - - /// Return the appropriate base type for the given instance size - PyObject *get_base(size_t instance_size); -}; - -/// Return a reference to the current 'internals' information -inline internals &get_internals(); - -/// from __cpp_future__ import (convenient aliases from C++14/17) -#ifdef PYBIND11_CPP14 -using std::enable_if_t; -using std::conditional_t; -using std::remove_cv_t; -#else -template <bool B, typename T = void> using enable_if_t = typename std::enable_if<B, T>::type; -template <bool B, typename T, typename F> using conditional_t = typename std::conditional<B, T, F>::type; -template <typename T> using remove_cv_t = typename std::remove_cv<T>::type; -#endif - -/// Index sequences -#if defined(PYBIND11_CPP14) || defined(_MSC_VER) -using std::index_sequence; -using std::make_index_sequence; -#else -template<size_t ...> struct index_sequence { }; -template<size_t N, size_t ...S> struct make_index_sequence_impl : make_index_sequence_impl <N - 1, N - 1, S...> { }; -template<size_t ...S> struct make_index_sequence_impl <0, S...> { typedef index_sequence<S...> type; }; -template<size_t N> using make_index_sequence = typename make_index_sequence_impl<N>::type; -#endif - -/// Backports of std::bool_constant and std::negation to accomodate older compilers -template <bool B> using bool_constant = std::integral_constant<bool, B>; -template <typename T> struct negation : bool_constant<!T::value> { }; - -template <typename...> struct void_t_impl { using type = void; }; -template <typename... Ts> using void_t = typename void_t_impl<Ts...>::type; - -/// Compile-time all/any/none of that check the boolean value of all template types -#ifdef __cpp_fold_expressions -template <class... Ts> using all_of = bool_constant<(Ts::value && ...)>; -template <class... Ts> using any_of = bool_constant<(Ts::value || ...)>; -#elif !defined(_MSC_VER) -template <bool...> struct bools {}; -template <class... Ts> using all_of = std::is_same< - bools<Ts::value..., true>, - bools<true, Ts::value...>>; -template <class... Ts> using any_of = negation<all_of<negation<Ts>...>>; -#else -// MSVC has trouble with the above, but supports std::conjunction, which we can use instead (albeit -// at a slight loss of compilation efficiency). -template <class... Ts> using all_of = std::conjunction<Ts...>; -template <class... Ts> using any_of = std::disjunction<Ts...>; -#endif -template <class... Ts> using none_of = negation<any_of<Ts...>>; - -template <class T, template<class> class... Predicates> using satisfies_all_of = all_of<Predicates<T>...>; -template <class T, template<class> class... Predicates> using satisfies_any_of = any_of<Predicates<T>...>; -template <class T, template<class> class... Predicates> using satisfies_none_of = none_of<Predicates<T>...>; - -/// Strip the class from a method type -template <typename T> struct remove_class { }; -template <typename C, typename R, typename... A> struct remove_class<R (C::*)(A...)> { typedef R type(A...); }; -template <typename C, typename R, typename... A> struct remove_class<R (C::*)(A...) const> { typedef R type(A...); }; - -/// Helper template to strip away type modifiers -template <typename T> struct intrinsic_type { typedef T type; }; -template <typename T> struct intrinsic_type<const T> { typedef typename intrinsic_type<T>::type type; }; -template <typename T> struct intrinsic_type<T*> { typedef typename intrinsic_type<T>::type type; }; -template <typename T> struct intrinsic_type<T&> { typedef typename intrinsic_type<T>::type type; }; -template <typename T> struct intrinsic_type<T&&> { typedef typename intrinsic_type<T>::type type; }; -template <typename T, size_t N> struct intrinsic_type<const T[N]> { typedef typename intrinsic_type<T>::type type; }; -template <typename T, size_t N> struct intrinsic_type<T[N]> { typedef typename intrinsic_type<T>::type type; }; -template <typename T> using intrinsic_t = typename intrinsic_type<T>::type; - -/// Helper type to replace 'void' in some expressions -struct void_type { }; - -/// Helper template which holds a list of types -template <typename...> struct type_list { }; - -/// Compile-time integer sum -#ifdef __cpp_fold_expressions -template <typename... Ts> constexpr size_t constexpr_sum(Ts... ns) { return (0 + ... + size_t{ns}); } -#else -constexpr size_t constexpr_sum() { return 0; } -template <typename T, typename... Ts> -constexpr size_t constexpr_sum(T n, Ts... ns) { return size_t{n} + constexpr_sum(ns...); } -#endif - -NAMESPACE_BEGIN(constexpr_impl) -/// Implementation details for constexpr functions -constexpr int first(int i) { return i; } -template <typename T, typename... Ts> -constexpr int first(int i, T v, Ts... vs) { return v ? i : first(i + 1, vs...); } - -constexpr int last(int /*i*/, int result) { return result; } -template <typename T, typename... Ts> -constexpr int last(int i, int result, T v, Ts... vs) { return last(i + 1, v ? i : result, vs...); } -NAMESPACE_END(constexpr_impl) - -/// Return the index of the first type in Ts which satisfies Predicate<T>. Returns sizeof...(Ts) if -/// none match. -template <template<typename> class Predicate, typename... Ts> -constexpr int constexpr_first() { return constexpr_impl::first(0, Predicate<Ts>::value...); } - -/// Return the index of the last type in Ts which satisfies Predicate<T>, or -1 if none match. -template <template<typename> class Predicate, typename... Ts> -constexpr int constexpr_last() { return constexpr_impl::last(0, -1, Predicate<Ts>::value...); } - -// Extracts the first type from the template parameter pack matching the predicate, or Default if none match. -template <template<class> class Predicate, class Default, class... Ts> struct first_of; -template <template<class> class Predicate, class Default> struct first_of<Predicate, Default> { - using type = Default; -}; -template <template<class> class Predicate, class Default, class T, class... Ts> -struct first_of<Predicate, Default, T, Ts...> { - using type = typename std::conditional< - Predicate<T>::value, - T, - typename first_of<Predicate, Default, Ts...>::type - >::type; -}; -template <template<class> class Predicate, class Default, class... T> using first_of_t = typename first_of<Predicate, Default, T...>::type; - -/// Defer the evaluation of type T until types Us are instantiated -template <typename T, typename... /*Us*/> struct deferred_type { using type = T; }; -template <typename T, typename... Us> using deferred_t = typename deferred_type<T, Us...>::type; - -template <template<typename...> class Base> -struct is_template_base_of_impl { - template <typename... Us> static std::true_type check(Base<Us...> *); - static std::false_type check(...); -}; - -/// Check if a template is the base of a type. For example: -/// `is_template_base_of<Base, T>` is true if `struct T : Base<U> {}` where U can be anything -template <template<typename...> class Base, typename T> -#if !defined(_MSC_VER) -using is_template_base_of = decltype(is_template_base_of_impl<Base>::check((remove_cv_t<T>*)nullptr)); -#else // MSVC2015 has trouble with decltype in template aliases -struct is_template_base_of : decltype(is_template_base_of_impl<Base>::check((remove_cv_t<T>*)nullptr)) { }; -#endif - -/// Check if T is std::shared_ptr<U> where U can be anything -template <typename T> struct is_shared_ptr : std::false_type { }; -template <typename U> struct is_shared_ptr<std::shared_ptr<U>> : std::true_type { }; - -/// Ignore that a variable is unused in compiler warnings -inline void ignore_unused(const int *) { } - -NAMESPACE_END(detail) - -/// Returns a named pointer that is shared among all extension modules (using the same -/// pybind11 version) running in the current interpreter. Names starting with underscores -/// are reserved for internal usage. Returns `nullptr` if no matching entry was found. -inline PYBIND11_NOINLINE void* get_shared_data(const std::string& name) { - auto& internals = detail::get_internals(); - auto it = internals.shared_data.find(name); - return it != internals.shared_data.end() ? it->second : nullptr; -} - -/// Set the shared data that can be later recovered by `get_shared_data()`. -inline PYBIND11_NOINLINE void *set_shared_data(const std::string& name, void *data) { - detail::get_internals().shared_data[name] = data; - return data; -} - -/// Returns a typed reference to a shared data entry (by using `get_shared_data()`) if -/// such entry exists. Otherwise, a new object of default-constructible type `T` is -/// added to the shared data under the given name and a reference to it is returned. -template<typename T> T& get_or_create_shared_data(const std::string& name) { - auto& internals = detail::get_internals(); - auto it = internals.shared_data.find(name); - T* ptr = (T*) (it != internals.shared_data.end() ? it->second : nullptr); - if (!ptr) { - ptr = new T(); - internals.shared_data[name] = ptr; - } - return *ptr; -} - -/// Fetch and hold an error which was already set in Python -class error_already_set : public std::runtime_error { -public: - error_already_set() : std::runtime_error(detail::error_string()) { - PyErr_Fetch(&type, &value, &trace); - } - - error_already_set(const error_already_set &) = delete; - - error_already_set(error_already_set &&e) - : std::runtime_error(e.what()), type(e.type), value(e.value), - trace(e.trace) { e.type = e.value = e.trace = nullptr; } - - inline ~error_already_set(); // implementation in pybind11.h - - error_already_set& operator=(const error_already_set &) = delete; - - /// Give the error back to Python - void restore() { PyErr_Restore(type, value, trace); type = value = trace = nullptr; } - - /// Clear the held Python error state (the C++ `what()` message remains intact) - void clear() { restore(); PyErr_Clear(); } - -private: - PyObject *type, *value, *trace; -}; - -/// C++ bindings of builtin Python exceptions -class builtin_exception : public std::runtime_error { -public: - using std::runtime_error::runtime_error; - /// Set the error using the Python C API - virtual void set_error() const = 0; -}; - -#define PYBIND11_RUNTIME_EXCEPTION(name, type) \ - class name : public builtin_exception { public: \ - using builtin_exception::builtin_exception; \ - name() : name("") { } \ - void set_error() const override { PyErr_SetString(type, what()); } \ - }; - -PYBIND11_RUNTIME_EXCEPTION(stop_iteration, PyExc_StopIteration) -PYBIND11_RUNTIME_EXCEPTION(index_error, PyExc_IndexError) -PYBIND11_RUNTIME_EXCEPTION(key_error, PyExc_KeyError) -PYBIND11_RUNTIME_EXCEPTION(value_error, PyExc_ValueError) -PYBIND11_RUNTIME_EXCEPTION(type_error, PyExc_TypeError) -PYBIND11_RUNTIME_EXCEPTION(cast_error, PyExc_RuntimeError) /// Thrown when pybind11::cast or handle::call fail due to a type casting error -PYBIND11_RUNTIME_EXCEPTION(reference_cast_error, PyExc_RuntimeError) /// Used internally - -[[noreturn]] PYBIND11_NOINLINE inline void pybind11_fail(const char *reason) { throw std::runtime_error(reason); } -[[noreturn]] PYBIND11_NOINLINE inline void pybind11_fail(const std::string &reason) { throw std::runtime_error(reason); } - -template <typename T, typename SFINAE = void> struct format_descriptor { }; - -NAMESPACE_BEGIN(detail) -// Returns the index of the given type in the type char array below, and in the list in numpy.h -// The order here is: bool; 8 ints ((signed,unsigned)x(8,16,32,64)bits); float,double,long double; -// complex float,double,long double. Note that the long double types only participate when long -// double is actually longer than double (it isn't under MSVC). -// NB: not only the string below but also complex.h and numpy.h rely on this order. -template <typename T, typename SFINAE = void> struct is_fmt_numeric { static constexpr bool value = false; }; -template <typename T> struct is_fmt_numeric<T, enable_if_t<std::is_arithmetic<T>::value>> { - static constexpr bool value = true; - static constexpr int index = std::is_same<T, bool>::value ? 0 : 1 + ( - std::is_integral<T>::value ? detail::log2(sizeof(T))*2 + std::is_unsigned<T>::value : 8 + ( - std::is_same<T, double>::value ? 1 : std::is_same<T, long double>::value ? 2 : 0)); -}; -NAMESPACE_END(detail) - -template <typename T> struct format_descriptor<T, detail::enable_if_t<detail::is_fmt_numeric<T>::value>> { - static constexpr const char c = "?bBhHiIqQfdgFDG"[detail::is_fmt_numeric<T>::index]; - static constexpr const char value[2] = { c, '\0' }; - static std::string format() { return std::string(1, c); } -}; - -template <typename T> constexpr const char format_descriptor< - T, detail::enable_if_t<detail::is_fmt_numeric<T>::value>>::value[2]; - -NAMESPACE_BEGIN(detail) - -template <typename T, typename SFINAE = void> struct compare_buffer_info { - static bool compare(const buffer_info& b) { - return b.format == format_descriptor<T>::format() && b.itemsize == sizeof(T); - } -}; - -template <typename T> struct compare_buffer_info<T, detail::enable_if_t<std::is_integral<T>::value>> { - static bool compare(const buffer_info& b) { - return b.itemsize == sizeof(T) && (b.format == format_descriptor<T>::value || - ((sizeof(T) == sizeof(long)) && b.format == (std::is_unsigned<T>::value ? "L" : "l")) || - ((sizeof(T) == sizeof(size_t)) && b.format == (std::is_unsigned<T>::value ? "N" : "n"))); - } -}; - -NAMESPACE_END(detail) - -/// RAII wrapper that temporarily clears any Python error state -struct error_scope { - PyObject *type, *value, *trace; - error_scope() { PyErr_Fetch(&type, &value, &trace); } - ~error_scope() { PyErr_Restore(type, value, trace); } -}; - -/// Dummy destructor wrapper that can be used to expose classes with a private destructor -struct nodelete { template <typename T> void operator()(T*) { } }; - -// overload_cast requires variable templates: C++14 or MSVC -#if defined(PYBIND11_CPP14) || defined(_MSC_VER) -#define PYBIND11_OVERLOAD_CAST 1 - -NAMESPACE_BEGIN(detail) -template <typename... Args> -struct overload_cast_impl { - template <typename Return> - constexpr auto operator()(Return (*pf)(Args...)) const noexcept - -> decltype(pf) { return pf; } - - template <typename Return, typename Class> - constexpr auto operator()(Return (Class::*pmf)(Args...), std::false_type = {}) const noexcept - -> decltype(pmf) { return pmf; } - - template <typename Return, typename Class> - constexpr auto operator()(Return (Class::*pmf)(Args...) const, std::true_type) const noexcept - -> decltype(pmf) { return pmf; } -}; -NAMESPACE_END(detail) - -/// Syntax sugar for resolving overloaded function pointers: -/// - regular: static_cast<Return (Class::*)(Arg0, Arg1, Arg2)>(&Class::func) -/// - sweet: overload_cast<Arg0, Arg1, Arg2>(&Class::func) -template <typename... Args> -static constexpr detail::overload_cast_impl<Args...> overload_cast = {}; -// MSVC 2015 only accepts this particular initialization syntax for this variable template. - -/// Const member function selector for overload_cast -/// - regular: static_cast<Return (Class::*)(Arg) const>(&Class::func) -/// - sweet: overload_cast<Arg>(&Class::func, const_) -static constexpr auto const_ = std::true_type{}; - -#endif // overload_cast - -NAMESPACE_END(pybind11) +#include "detail/common.h" +#warning "Including 'common.h' is deprecated. It will be removed in v3.0. Use 'pybind11.h'." diff --git a/ext/pybind11/include/pybind11/complex.h b/ext/pybind11/include/pybind11/complex.h index 945ca0710..5dac27cc4 100644 --- a/ext/pybind11/include/pybind11/complex.h +++ b/ext/pybind11/include/pybind11/complex.h @@ -17,11 +17,20 @@ # undef I #endif -NAMESPACE_BEGIN(pybind11) +NAMESPACE_BEGIN(PYBIND11_NAMESPACE) + +template <typename T> struct format_descriptor<std::complex<T>, detail::enable_if_t<std::is_floating_point<T>::value>> { + static constexpr const char c = format_descriptor<T>::c; + static constexpr const char value[3] = { 'Z', c, '\0' }; + static std::string format() { return std::string(value); } +}; + +template <typename T> constexpr const char format_descriptor< + std::complex<T>, detail::enable_if_t<std::is_floating_point<T>::value>>::value[3]; + NAMESPACE_BEGIN(detail) -// The format codes are already in the string in common.h, we just need to provide a specialization -template <typename T> struct is_fmt_numeric<std::complex<T>> { +template <typename T> struct is_fmt_numeric<std::complex<T>, detail::enable_if_t<std::is_floating_point<T>::value>> { static constexpr bool value = true; static constexpr int index = is_fmt_numeric<T>::index + 3; }; @@ -49,4 +58,4 @@ public: PYBIND11_TYPE_CASTER(std::complex<T>, _("complex")); }; NAMESPACE_END(detail) -NAMESPACE_END(pybind11) +NAMESPACE_END(PYBIND11_NAMESPACE) diff --git a/ext/pybind11/include/pybind11/class_support.h b/ext/pybind11/include/pybind11/detail/class.h index 992703ff3..f745992a0 100644 --- a/ext/pybind11/include/pybind11/class_support.h +++ b/ext/pybind11/include/pybind11/detail/class.h @@ -1,5 +1,5 @@ /* - pybind11/class_support.h: Python C API implementation details for py::class_ + pybind11/detail/class.h: Python C API implementation details for py::class_ Copyright (c) 2017 Wenzel Jakob <wenzel.jakob@epfl.ch> @@ -9,11 +9,16 @@ #pragma once -#include "attr.h" +#include "../attr.h" -NAMESPACE_BEGIN(pybind11) +NAMESPACE_BEGIN(PYBIND11_NAMESPACE) NAMESPACE_BEGIN(detail) +inline PyTypeObject *type_incref(PyTypeObject *type) { + Py_INCREF(type); + return type; +} + #if !defined(PYPY_VERSION) /// `pybind11_static_property.__get__()`: Always pass the class instead of the instance. @@ -49,7 +54,7 @@ inline PyTypeObject *make_static_property_type() { auto type = &heap_type->ht_type; type->tp_name = name; - type->tp_base = &PyProperty_Type; + type->tp_base = type_incref(&PyProperty_Type); type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE; type->tp_descr_get = pybind11_static_get; type->tp_descr_set = pybind11_static_set; @@ -87,34 +92,6 @@ inline PyTypeObject *make_static_property_type() { #endif // PYPY -/** Inheriting from multiple C++ types in Python is not supported -- set an error instead. - A Python definition (`class C(A, B): pass`) will call `tp_new` so we check for multiple - C++ bases here. On the other hand, C++ type definitions (`py::class_<C, A, B>(m, "C")`) - don't not use `tp_new` and will not trigger this error. */ -extern "C" inline PyObject *pybind11_meta_new(PyTypeObject *metaclass, PyObject *args, - PyObject *kwargs) { - PyObject *bases = PyTuple_GetItem(args, 1); // arguments: (name, bases, dict) - if (!bases) - return nullptr; - - auto &internals = get_internals(); - auto num_cpp_bases = 0; - for (auto base : reinterpret_borrow<tuple>(bases)) { - auto base_type = (PyTypeObject *) base.ptr(); - auto instance_size = static_cast<size_t>(base_type->tp_basicsize); - if (PyObject_IsSubclass(base.ptr(), internals.get_base(instance_size))) - ++num_cpp_bases; - } - - if (num_cpp_bases > 1) { - PyErr_SetString(PyExc_TypeError, "Can't inherit from multiple C++ classes in Python." - "Use py::class_ to define the class in C++ instead."); - return nullptr; - } else { - return PyType_Type.tp_new(metaclass, args, kwargs); - } -} - /** Types with static properties need to handle `Type.static_prop = x` in a specific way. By default, Python replaces the `static_property` itself, but for wrapped C++ types we need to call `static_property.__set__()` in order to propagate the new value to @@ -124,8 +101,15 @@ extern "C" inline int pybind11_meta_setattro(PyObject* obj, PyObject* name, PyOb // descriptor (`property`) instead of calling `tp_descr_get` (`property.__get__()`). PyObject *descr = _PyType_Lookup((PyTypeObject *) obj, name); - // Call `static_property.__set__()` instead of replacing the `static_property`. - if (descr && PyObject_IsInstance(descr, (PyObject *) get_internals().static_property_type)) { + // The following assignment combinations are possible: + // 1. `Type.static_prop = value` --> descr_set: `Type.static_prop.__set__(value)` + // 2. `Type.static_prop = other_static_prop` --> setattro: replace existing `static_prop` + // 3. `Type.regular_attribute = value` --> setattro: regular attribute assignment + const auto static_prop = (PyObject *) get_internals().static_property_type; + const auto call_descr_set = descr && PyObject_IsInstance(descr, static_prop) + && !PyObject_IsInstance(value, static_prop); + if (call_descr_set) { + // Call `static_property.__set__()` instead of replacing the `static_property`. #if !defined(PYPY_VERSION) return Py_TYPE(descr)->tp_descr_set(descr, obj, value); #else @@ -137,10 +121,30 @@ extern "C" inline int pybind11_meta_setattro(PyObject* obj, PyObject* name, PyOb } #endif } else { + // Replace existing attribute. return PyType_Type.tp_setattro(obj, name, value); } } +#if PY_MAJOR_VERSION >= 3 +/** + * Python 3's PyInstanceMethod_Type hides itself via its tp_descr_get, which prevents aliasing + * methods via cls.attr("m2") = cls.attr("m1"): instead the tp_descr_get returns a plain function, + * when called on a class, or a PyMethod, when called on an instance. Override that behaviour here + * to do a special case bypass for PyInstanceMethod_Types. + */ +extern "C" inline PyObject *pybind11_meta_getattro(PyObject *obj, PyObject *name) { + PyObject *descr = _PyType_Lookup((PyTypeObject *) obj, name); + if (descr && PyInstanceMethod_Check(descr)) { + Py_INCREF(descr); + return descr; + } + else { + return PyType_Type.tp_getattro(obj, name); + } +} +#endif + /** This metaclass is assigned by default to all pybind11 types and is required in order for static properties to function correctly. Users may override this using `py::metaclass`. Return value: New reference. */ @@ -163,11 +167,13 @@ inline PyTypeObject* make_default_metaclass() { auto type = &heap_type->ht_type; type->tp_name = name; - type->tp_base = &PyType_Type; + type->tp_base = type_incref(&PyType_Type); type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE; - type->tp_new = pybind11_meta_new; type->tp_setattro = pybind11_meta_setattro; +#if PY_MAJOR_VERSION >= 3 + type->tp_getattro = pybind11_meta_getattro; +#endif if (PyType_Ready(type) < 0) pybind11_fail("make_default_metaclass(): failure in PyType_Ready()!"); @@ -177,17 +183,81 @@ inline PyTypeObject* make_default_metaclass() { return type; } +/// For multiple inheritance types we need to recursively register/deregister base pointers for any +/// base classes with pointers that are difference from the instance value pointer so that we can +/// correctly recognize an offset base class pointer. This calls a function with any offset base ptrs. +inline void traverse_offset_bases(void *valueptr, const detail::type_info *tinfo, instance *self, + bool (*f)(void * /*parentptr*/, instance * /*self*/)) { + for (handle h : reinterpret_borrow<tuple>(tinfo->type->tp_bases)) { + if (auto parent_tinfo = get_type_info((PyTypeObject *) h.ptr())) { + for (auto &c : parent_tinfo->implicit_casts) { + if (c.first == tinfo->cpptype) { + auto *parentptr = c.second(valueptr); + if (parentptr != valueptr) + f(parentptr, self); + traverse_offset_bases(parentptr, parent_tinfo, self, f); + break; + } + } + } + } +} + +inline bool register_instance_impl(void *ptr, instance *self) { + get_internals().registered_instances.emplace(ptr, self); + return true; // unused, but gives the same signature as the deregister func +} +inline bool deregister_instance_impl(void *ptr, instance *self) { + auto ®istered_instances = get_internals().registered_instances; + auto range = registered_instances.equal_range(ptr); + for (auto it = range.first; it != range.second; ++it) { + if (Py_TYPE(self) == Py_TYPE(it->second)) { + registered_instances.erase(it); + return true; + } + } + return false; +} + +inline void register_instance(instance *self, void *valptr, const type_info *tinfo) { + register_instance_impl(valptr, self); + if (!tinfo->simple_ancestors) + traverse_offset_bases(valptr, tinfo, self, register_instance_impl); +} + +inline bool deregister_instance(instance *self, void *valptr, const type_info *tinfo) { + bool ret = deregister_instance_impl(valptr, self); + if (!tinfo->simple_ancestors) + traverse_offset_bases(valptr, tinfo, self, deregister_instance_impl); + return ret; +} + +/// Instance creation function for all pybind11 types. It allocates the internal instance layout for +/// holding C++ objects and holders. Allocation is done lazily (the first time the instance is cast +/// to a reference or pointer), and initialization is done by an `__init__` function. +inline PyObject *make_new_instance(PyTypeObject *type) { +#if defined(PYPY_VERSION) + // PyPy gets tp_basicsize wrong (issue 2482) under multiple inheritance when the first inherited + // object is a a plain Python type (i.e. not derived from an extension type). Fix it. + ssize_t instance_size = static_cast<ssize_t>(sizeof(instance)); + if (type->tp_basicsize < instance_size) { + type->tp_basicsize = instance_size; + } +#endif + PyObject *self = type->tp_alloc(type, 0); + auto inst = reinterpret_cast<instance *>(self); + // Allocate the value/holder internals: + inst->allocate_layout(); + + inst->owned = true; + + return self; +} + /// Instance creation function for all pybind11 types. It only allocates space for the /// C++ object, but doesn't call the constructor -- an `__init__` function must do that. extern "C" inline PyObject *pybind11_object_new(PyTypeObject *type, PyObject *, PyObject *) { - PyObject *self = type->tp_alloc(type, 0); - auto instance = (instance_essentials<void> *) self; - auto tinfo = get_type_info(type); - instance->value = tinfo->operator_new(tinfo->type_size); - instance->owned = true; - instance->holder_constructed = false; - get_internals().registered_instances.emplace(instance->value, self); - return self; + return make_new_instance(type); } /// An `__init__` function constructs the C++ object. Users should provide at least one @@ -205,50 +275,89 @@ extern "C" inline int pybind11_object_init(PyObject *self, PyObject *, PyObject return -1; } -/// Instance destructor function for all pybind11 types. It calls `type_info.dealloc` -/// to destroy the C++ object itself, while the rest is Python bookkeeping. -extern "C" inline void pybind11_object_dealloc(PyObject *self) { - auto instance = (instance_essentials<void> *) self; - if (instance->value) { - auto type = Py_TYPE(self); - get_type_info(type)->dealloc(self); - - auto ®istered_instances = get_internals().registered_instances; - auto range = registered_instances.equal_range(instance->value); - bool found = false; - for (auto it = range.first; it != range.second; ++it) { - if (type == Py_TYPE(it->second)) { - registered_instances.erase(it); - found = true; - break; - } - } - if (!found) - pybind11_fail("pybind11_object_dealloc(): Tried to deallocate unregistered instance!"); +inline void add_patient(PyObject *nurse, PyObject *patient) { + auto &internals = get_internals(); + auto instance = reinterpret_cast<detail::instance *>(nurse); + instance->has_patients = true; + Py_INCREF(patient); + internals.patients[nurse].push_back(patient); +} + +inline void clear_patients(PyObject *self) { + auto instance = reinterpret_cast<detail::instance *>(self); + auto &internals = get_internals(); + auto pos = internals.patients.find(self); + assert(pos != internals.patients.end()); + // Clearing the patients can cause more Python code to run, which + // can invalidate the iterator. Extract the vector of patients + // from the unordered_map first. + auto patients = std::move(pos->second); + internals.patients.erase(pos); + instance->has_patients = false; + for (PyObject *&patient : patients) + Py_CLEAR(patient); +} + +/// Clears all internal data from the instance and removes it from registered instances in +/// preparation for deallocation. +inline void clear_instance(PyObject *self) { + auto instance = reinterpret_cast<detail::instance *>(self); - if (instance->weakrefs) - PyObject_ClearWeakRefs(self); + // Deallocate any values/holders, if present: + for (auto &v_h : values_and_holders(instance)) { + if (v_h) { - PyObject **dict_ptr = _PyObject_GetDictPtr(self); - if (dict_ptr) - Py_CLEAR(*dict_ptr); + // We have to deregister before we call dealloc because, for virtual MI types, we still + // need to be able to get the parent pointers. + if (v_h.instance_registered() && !deregister_instance(instance, v_h.value_ptr(), v_h.type)) + pybind11_fail("pybind11_object_dealloc(): Tried to deallocate unregistered instance!"); + + if (instance->owned || v_h.holder_constructed()) + v_h.type->dealloc(v_h); + } } - Py_TYPE(self)->tp_free(self); + // Deallocate the value/holder layout internals: + instance->deallocate_layout(); + + if (instance->weakrefs) + PyObject_ClearWeakRefs(self); + + PyObject **dict_ptr = _PyObject_GetDictPtr(self); + if (dict_ptr) + Py_CLEAR(*dict_ptr); + + if (instance->has_patients) + clear_patients(self); +} + +/// Instance destructor function for all pybind11 types. It calls `type_info.dealloc` +/// to destroy the C++ object itself, while the rest is Python bookkeeping. +extern "C" inline void pybind11_object_dealloc(PyObject *self) { + clear_instance(self); + + auto type = Py_TYPE(self); + type->tp_free(self); + + // `type->tp_dealloc != pybind11_object_dealloc` means that we're being called + // as part of a derived type's dealloc, in which case we're not allowed to decref + // the type here. For cross-module compatibility, we shouldn't compare directly + // with `pybind11_object_dealloc`, but with the common one stashed in internals. + auto pybind11_object_type = (PyTypeObject *) get_internals().instance_base; + if (type->tp_dealloc == pybind11_object_type->tp_dealloc) + Py_DECREF(type); } -/** Create a type which can be used as a common base for all classes with the same - instance size, i.e. all classes with the same `sizeof(holder_type)`. This is +/** Create the type which can be used as a common base for all classes. This is needed in order to satisfy Python's requirements for multiple inheritance. Return value: New reference. */ -inline PyObject *make_object_base_type(size_t instance_size) { - auto name = "pybind11_object_" + std::to_string(instance_size); - auto name_obj = reinterpret_steal<object>(PYBIND11_FROM_STRING(name.c_str())); +inline PyObject *make_object_base_type(PyTypeObject *metaclass) { + constexpr auto *name = "pybind11_object"; + auto name_obj = reinterpret_steal<object>(PYBIND11_FROM_STRING(name)); /* Danger zone: from now (and until PyType_Ready), make sure to issue no Python C API calls which could potentially invoke the garbage collector (the GC will call type_traverse(), which will in turn find the newly constructed type in an invalid state) */ - auto metaclass = get_internals().default_metaclass; auto heap_type = (PyHeapTypeObject *) metaclass->tp_alloc(metaclass, 0); if (!heap_type) pybind11_fail("make_object_base_type(): error allocating type!"); @@ -259,9 +368,9 @@ inline PyObject *make_object_base_type(size_t instance_size) { #endif auto type = &heap_type->ht_type; - type->tp_name = strdup(name.c_str()); - type->tp_base = &PyBaseObject_Type; - type->tp_basicsize = static_cast<ssize_t>(instance_size); + type->tp_name = name; + type->tp_base = type_incref(&PyBaseObject_Type); + type->tp_basicsize = static_cast<ssize_t>(sizeof(instance)); type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE; type->tp_new = pybind11_object_new; @@ -269,7 +378,7 @@ inline PyObject *make_object_base_type(size_t instance_size) { type->tp_dealloc = pybind11_object_dealloc; /* Support weak references (needed for the keep_alive feature) */ - type->tp_weaklistoffset = offsetof(instance_essentials<void>, weakrefs); + type->tp_weaklistoffset = offsetof(instance, weakrefs); if (PyType_Ready(type) < 0) pybind11_fail("PyType_Ready failed in make_object_base_type():" + error_string()); @@ -280,20 +389,6 @@ inline PyObject *make_object_base_type(size_t instance_size) { return (PyObject *) heap_type; } -/** Return the appropriate base type for the given instance size. The results are cached - in `internals.bases` so that only a single base is ever created for any size value. - Return value: Borrowed reference. */ -inline PyObject *internals::get_base(size_t instance_size) { - auto it = bases.find(instance_size); - if (it != bases.end()) { - return it->second; - } else { - auto base = make_object_base_type(instance_size); - bases[instance_size] = base; - return base; - } -} - /// dynamic_attr: Support for `d = instance.__dict__`. extern "C" inline PyObject *pybind11_get_dict(PyObject *self, void *) { PyObject *&dict = *_PyObject_GetDictPtr(self); @@ -341,7 +436,7 @@ inline void enable_dynamic_attributes(PyHeapTypeObject *heap_type) { #endif type->tp_flags |= Py_TPFLAGS_HAVE_GC; type->tp_dictoffset = type->tp_basicsize; // place dict at the end - type->tp_basicsize += sizeof(PyObject *); // and allocate enough space for it + type->tp_basicsize += (ssize_t)sizeof(PyObject *); // and allocate enough space for it type->tp_traverse = pybind11_traverse; type->tp_clear = pybind11_clear; @@ -354,20 +449,26 @@ inline void enable_dynamic_attributes(PyHeapTypeObject *heap_type) { /// buffer_protocol: Fill in the view as specified by flags. extern "C" inline int pybind11_getbuffer(PyObject *obj, Py_buffer *view, int flags) { - auto tinfo = get_type_info(Py_TYPE(obj)); + // Look for a `get_buffer` implementation in this type's info or any bases (following MRO). + type_info *tinfo = nullptr; + for (auto type : reinterpret_borrow<tuple>(Py_TYPE(obj)->tp_mro)) { + tinfo = get_type_info((PyTypeObject *) type.ptr()); + if (tinfo && tinfo->get_buffer) + break; + } if (view == nullptr || obj == nullptr || !tinfo || !tinfo->get_buffer) { if (view) view->obj = nullptr; - PyErr_SetString(PyExc_BufferError, "generic_type::getbuffer(): Internal error"); + PyErr_SetString(PyExc_BufferError, "pybind11_getbuffer(): Internal error"); return -1; } - memset(view, 0, sizeof(Py_buffer)); + std::memset(view, 0, sizeof(Py_buffer)); buffer_info *info = tinfo->get_buffer(obj, tinfo->get_buffer_data); view->obj = obj; view->ndim = 1; view->internal = info; view->buf = info->ptr; - view->itemsize = (ssize_t) info->itemsize; + view->itemsize = info->itemsize; view->len = view->itemsize; for (auto s : info->shape) view->len *= s; @@ -375,8 +476,8 @@ extern "C" inline int pybind11_getbuffer(PyObject *obj, Py_buffer *view, int fla view->format = const_cast<char *>(info->format.c_str()); if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) { view->ndim = (int) info->ndim; - view->strides = (ssize_t *) &info->strides[0]; - view->shape = (ssize_t *) &info->shape[0]; + view->strides = &info->strides[0]; + view->shape = &info->shape[0]; } Py_INCREF(view->obj); return 0; @@ -419,12 +520,11 @@ inline PyObject* make_new_python_type(const type_record &rec) { module = rec.scope.attr("__name__"); } + auto full_name = c_str( #if !defined(PYPY_VERSION) - const auto full_name = module ? str(module).cast<std::string>() + "." + rec.name - : std::string(rec.name); -#else - const auto full_name = std::string(rec.name); + module ? str(module).cast<std::string>() + "." + rec.name : #endif + rec.name); char *tp_doc = nullptr; if (rec.doc && options::show_user_defined_docstrings()) { @@ -437,7 +537,7 @@ inline PyObject* make_new_python_type(const type_record &rec) { auto &internals = get_internals(); auto bases = tuple(rec.bases); - auto base = (bases.size() == 0) ? internals.get_base(rec.instance_size) + auto base = (bases.size() == 0) ? internals.instance_base : bases[0].ptr(); /* Danger zone: from now (and until PyType_Ready), make sure to @@ -457,10 +557,10 @@ inline PyObject* make_new_python_type(const type_record &rec) { #endif auto type = &heap_type->ht_type; - type->tp_name = strdup(full_name.c_str()); + type->tp_name = full_name; type->tp_doc = tp_doc; - type->tp_base = (PyTypeObject *) handle(base).inc_ref().ptr(); - type->tp_basicsize = static_cast<ssize_t>(rec.instance_size); + type->tp_base = type_incref((PyTypeObject *)base); + type->tp_basicsize = static_cast<ssize_t>(sizeof(instance)); if (bases.size() > 0) type->tp_bases = bases.release().ptr(); @@ -493,6 +593,8 @@ inline PyObject* make_new_python_type(const type_record &rec) { /* Register type with the parent scope */ if (rec.scope) setattr(rec.scope, rec.name, (PyObject *) type); + else + Py_INCREF(type); // Keep it alive forever (reference leak) if (module) // Needed by pydoc setattr((PyObject *) type, "__module__", module); @@ -501,4 +603,4 @@ inline PyObject* make_new_python_type(const type_record &rec) { } NAMESPACE_END(detail) -NAMESPACE_END(pybind11) +NAMESPACE_END(PYBIND11_NAMESPACE) diff --git a/ext/pybind11/include/pybind11/detail/common.h b/ext/pybind11/include/pybind11/detail/common.h new file mode 100644 index 000000000..8f763f08a --- /dev/null +++ b/ext/pybind11/include/pybind11/detail/common.h @@ -0,0 +1,800 @@ +/* + pybind11/detail/common.h -- Basic macros + + Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch> + + All rights reserved. Use of this source code is governed by a + BSD-style license that can be found in the LICENSE file. +*/ + +#pragma once + +#if !defined(NAMESPACE_BEGIN) +# define NAMESPACE_BEGIN(name) namespace name { +#endif +#if !defined(NAMESPACE_END) +# define NAMESPACE_END(name) } +#endif + +// Robust support for some features and loading modules compiled against different pybind versions +// requires forcing hidden visibility on pybind code, so we enforce this by setting the attribute on +// the main `pybind11` namespace. +#if !defined(PYBIND11_NAMESPACE) +# ifdef __GNUG__ +# define PYBIND11_NAMESPACE pybind11 __attribute__((visibility("hidden"))) +# else +# define PYBIND11_NAMESPACE pybind11 +# endif +#endif + +#if !defined(_MSC_VER) && !defined(__INTEL_COMPILER) +# if __cplusplus >= 201402L +# define PYBIND11_CPP14 +# if __cplusplus > 201402L /* Temporary: should be updated to >= the final C++17 value once known */ +# define PYBIND11_CPP17 +# endif +# endif +#elif defined(_MSC_VER) +// MSVC sets _MSVC_LANG rather than __cplusplus (supposedly until the standard is fully implemented) +# if _MSVC_LANG >= 201402L +# define PYBIND11_CPP14 +# if _MSVC_LANG > 201402L && _MSC_VER >= 1910 +# define PYBIND11_CPP17 +# endif +# endif +#endif + +// Compiler version assertions +#if defined(__INTEL_COMPILER) +# if __INTEL_COMPILER < 1500 +# error pybind11 requires Intel C++ compiler v15 or newer +# endif +#elif defined(__clang__) && !defined(__apple_build_version__) +# if __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 3) +# error pybind11 requires clang 3.3 or newer +# endif +#elif defined(__clang__) +// Apple changes clang version macros to its Xcode version; the first Xcode release based on +// (upstream) clang 3.3 was Xcode 5: +# if __clang_major__ < 5 +# error pybind11 requires Xcode/clang 5.0 or newer +# endif +#elif defined(__GNUG__) +# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8) +# error pybind11 requires gcc 4.8 or newer +# endif +#elif defined(_MSC_VER) +// Pybind hits various compiler bugs in 2015u2 and earlier, and also makes use of some stl features +// (e.g. std::negation) added in 2015u3: +# if _MSC_FULL_VER < 190024210 +# error pybind11 requires MSVC 2015 update 3 or newer +# endif +#endif + +#if !defined(PYBIND11_EXPORT) +# if defined(WIN32) || defined(_WIN32) +# define PYBIND11_EXPORT __declspec(dllexport) +# else +# define PYBIND11_EXPORT __attribute__ ((visibility("default"))) +# endif +#endif + +#if defined(_MSC_VER) +# define PYBIND11_NOINLINE __declspec(noinline) +#else +# define PYBIND11_NOINLINE __attribute__ ((noinline)) +#endif + +#if defined(PYBIND11_CPP14) +# define PYBIND11_DEPRECATED(reason) [[deprecated(reason)]] +#else +# define PYBIND11_DEPRECATED(reason) __attribute__((deprecated(reason))) +#endif + +#define PYBIND11_VERSION_MAJOR 2 +#define PYBIND11_VERSION_MINOR 2 +#define PYBIND11_VERSION_PATCH 1 + +/// Include Python header, disable linking to pythonX_d.lib on Windows in debug mode +#if defined(_MSC_VER) +# if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 4) +# define HAVE_ROUND 1 +# endif +# pragma warning(push) +# pragma warning(disable: 4510 4610 4512 4005) +# if defined(_DEBUG) +# define PYBIND11_DEBUG_MARKER +# undef _DEBUG +# endif +#endif + +#include <Python.h> +#include <frameobject.h> +#include <pythread.h> + +#if defined(_WIN32) && (defined(min) || defined(max)) +# error Macro clash with min and max -- define NOMINMAX when compiling your program on Windows +#endif + +#if defined(isalnum) +# undef isalnum +# undef isalpha +# undef islower +# undef isspace +# undef isupper +# undef tolower +# undef toupper +#endif + +#if defined(_MSC_VER) +# if defined(PYBIND11_DEBUG_MARKER) +# define _DEBUG +# undef PYBIND11_DEBUG_MARKER +# endif +# pragma warning(pop) +#endif + +#include <cstddef> +#include <cstring> +#include <forward_list> +#include <vector> +#include <string> +#include <stdexcept> +#include <unordered_set> +#include <unordered_map> +#include <memory> +#include <typeindex> +#include <type_traits> + +#if PY_MAJOR_VERSION >= 3 /// Compatibility macros for various Python versions +#define PYBIND11_INSTANCE_METHOD_NEW(ptr, class_) PyInstanceMethod_New(ptr) +#define PYBIND11_INSTANCE_METHOD_CHECK PyInstanceMethod_Check +#define PYBIND11_INSTANCE_METHOD_GET_FUNCTION PyInstanceMethod_GET_FUNCTION +#define PYBIND11_BYTES_CHECK PyBytes_Check +#define PYBIND11_BYTES_FROM_STRING PyBytes_FromString +#define PYBIND11_BYTES_FROM_STRING_AND_SIZE PyBytes_FromStringAndSize +#define PYBIND11_BYTES_AS_STRING_AND_SIZE PyBytes_AsStringAndSize +#define PYBIND11_BYTES_AS_STRING PyBytes_AsString +#define PYBIND11_BYTES_SIZE PyBytes_Size +#define PYBIND11_LONG_CHECK(o) PyLong_Check(o) +#define PYBIND11_LONG_AS_LONGLONG(o) PyLong_AsLongLong(o) +#define PYBIND11_BYTES_NAME "bytes" +#define PYBIND11_STRING_NAME "str" +#define PYBIND11_SLICE_OBJECT PyObject +#define PYBIND11_FROM_STRING PyUnicode_FromString +#define PYBIND11_STR_TYPE ::pybind11::str +#define PYBIND11_BOOL_ATTR "__bool__" +#define PYBIND11_NB_BOOL(ptr) ((ptr)->nb_bool) +#define PYBIND11_PLUGIN_IMPL(name) \ + extern "C" PYBIND11_EXPORT PyObject *PyInit_##name() + +#else +#define PYBIND11_INSTANCE_METHOD_NEW(ptr, class_) PyMethod_New(ptr, nullptr, class_) +#define PYBIND11_INSTANCE_METHOD_CHECK PyMethod_Check +#define PYBIND11_INSTANCE_METHOD_GET_FUNCTION PyMethod_GET_FUNCTION +#define PYBIND11_BYTES_CHECK PyString_Check +#define PYBIND11_BYTES_FROM_STRING PyString_FromString +#define PYBIND11_BYTES_FROM_STRING_AND_SIZE PyString_FromStringAndSize +#define PYBIND11_BYTES_AS_STRING_AND_SIZE PyString_AsStringAndSize +#define PYBIND11_BYTES_AS_STRING PyString_AsString +#define PYBIND11_BYTES_SIZE PyString_Size +#define PYBIND11_LONG_CHECK(o) (PyInt_Check(o) || PyLong_Check(o)) +#define PYBIND11_LONG_AS_LONGLONG(o) (PyInt_Check(o) ? (long long) PyLong_AsLong(o) : PyLong_AsLongLong(o)) +#define PYBIND11_BYTES_NAME "str" +#define PYBIND11_STRING_NAME "unicode" +#define PYBIND11_SLICE_OBJECT PySliceObject +#define PYBIND11_FROM_STRING PyString_FromString +#define PYBIND11_STR_TYPE ::pybind11::bytes +#define PYBIND11_BOOL_ATTR "__nonzero__" +#define PYBIND11_NB_BOOL(ptr) ((ptr)->nb_nonzero) +#define PYBIND11_PLUGIN_IMPL(name) \ + static PyObject *pybind11_init_wrapper(); \ + extern "C" PYBIND11_EXPORT void init##name() { \ + (void)pybind11_init_wrapper(); \ + } \ + PyObject *pybind11_init_wrapper() +#endif + +#if PY_VERSION_HEX >= 0x03050000 && PY_VERSION_HEX < 0x03050200 +extern "C" { + struct _Py_atomic_address { void *value; }; + PyAPI_DATA(_Py_atomic_address) _PyThreadState_Current; +} +#endif + +#define PYBIND11_TRY_NEXT_OVERLOAD ((PyObject *) 1) // special failure return code +#define PYBIND11_STRINGIFY(x) #x +#define PYBIND11_TOSTRING(x) PYBIND11_STRINGIFY(x) +#define PYBIND11_CONCAT(first, second) first##second + +/** \rst + ***Deprecated in favor of PYBIND11_MODULE*** + + This macro creates the entry point that will be invoked when the Python interpreter + imports a plugin library. Please create a `module` in the function body and return + the pointer to its underlying Python object at the end. + + .. code-block:: cpp + + PYBIND11_PLUGIN(example) { + pybind11::module m("example", "pybind11 example plugin"); + /// Set up bindings here + return m.ptr(); + } +\endrst */ +#define PYBIND11_PLUGIN(name) \ + PYBIND11_DEPRECATED("PYBIND11_PLUGIN is deprecated, use PYBIND11_MODULE") \ + static PyObject *pybind11_init(); \ + PYBIND11_PLUGIN_IMPL(name) { \ + int major, minor; \ + if (sscanf(Py_GetVersion(), "%i.%i", &major, &minor) != 2) { \ + PyErr_SetString(PyExc_ImportError, "Can't parse Python version."); \ + return nullptr; \ + } else if (major != PY_MAJOR_VERSION || minor != PY_MINOR_VERSION) { \ + PyErr_Format(PyExc_ImportError, \ + "Python version mismatch: module was compiled for " \ + "version %i.%i, while the interpreter is running " \ + "version %i.%i.", PY_MAJOR_VERSION, PY_MINOR_VERSION, \ + major, minor); \ + return nullptr; \ + } \ + try { \ + return pybind11_init(); \ + } catch (pybind11::error_already_set &e) { \ + PyErr_SetString(PyExc_ImportError, e.what()); \ + return nullptr; \ + } catch (const std::exception &e) { \ + PyErr_SetString(PyExc_ImportError, e.what()); \ + return nullptr; \ + } \ + } \ + PyObject *pybind11_init() + +/** \rst + This macro creates the entry point that will be invoked when the Python interpreter + imports an extension module. The module name is given as the fist argument and it + should not be in quotes. The second macro argument defines a variable of type + `py::module` which can be used to initialize the module. + + .. code-block:: cpp + + PYBIND11_MODULE(example, m) { + m.doc() = "pybind11 example module"; + + // Add bindings here + m.def("foo", []() { + return "Hello, World!"; + }); + } +\endrst */ +#define PYBIND11_MODULE(name, variable) \ + static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \ + PYBIND11_PLUGIN_IMPL(name) { \ + int major, minor; \ + if (sscanf(Py_GetVersion(), "%i.%i", &major, &minor) != 2) { \ + PyErr_SetString(PyExc_ImportError, "Can't parse Python version."); \ + return nullptr; \ + } else if (major != PY_MAJOR_VERSION || minor != PY_MINOR_VERSION) { \ + PyErr_Format(PyExc_ImportError, \ + "Python version mismatch: module was compiled for " \ + "version %i.%i, while the interpreter is running " \ + "version %i.%i.", PY_MAJOR_VERSION, PY_MINOR_VERSION, \ + major, minor); \ + return nullptr; \ + } \ + auto m = pybind11::module(PYBIND11_TOSTRING(name)); \ + try { \ + PYBIND11_CONCAT(pybind11_init_, name)(m); \ + return m.ptr(); \ + } catch (pybind11::error_already_set &e) { \ + PyErr_SetString(PyExc_ImportError, e.what()); \ + return nullptr; \ + } catch (const std::exception &e) { \ + PyErr_SetString(PyExc_ImportError, e.what()); \ + return nullptr; \ + } \ + } \ + void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &variable) + + +NAMESPACE_BEGIN(PYBIND11_NAMESPACE) + +using ssize_t = Py_ssize_t; +using size_t = std::size_t; + +/// Approach used to cast a previously unknown C++ instance into a Python object +enum class return_value_policy : uint8_t { + /** This is the default return value policy, which falls back to the policy + return_value_policy::take_ownership when the return value is a pointer. + Otherwise, it uses return_value::move or return_value::copy for rvalue + and lvalue references, respectively. See below for a description of what + all of these different policies do. */ + automatic = 0, + + /** As above, but use policy return_value_policy::reference when the return + value is a pointer. This is the default conversion policy for function + arguments when calling Python functions manually from C++ code (i.e. via + handle::operator()). You probably won't need to use this. */ + automatic_reference, + + /** Reference an existing object (i.e. do not create a new copy) and take + ownership. Python will call the destructor and delete operator when the + object’s reference count reaches zero. Undefined behavior ensues when + the C++ side does the same.. */ + take_ownership, + + /** Create a new copy of the returned object, which will be owned by + Python. This policy is comparably safe because the lifetimes of the two + instances are decoupled. */ + copy, + + /** Use std::move to move the return value contents into a new instance + that will be owned by Python. This policy is comparably safe because the + lifetimes of the two instances (move source and destination) are + decoupled. */ + move, + + /** Reference an existing object, but do not take ownership. The C++ side + is responsible for managing the object’s lifetime and deallocating it + when it is no longer used. Warning: undefined behavior will ensue when + the C++ side deletes an object that is still referenced and used by + Python. */ + reference, + + /** This policy only applies to methods and properties. It references the + object without taking ownership similar to the above + return_value_policy::reference policy. In contrast to that policy, the + function or property’s implicit this argument (called the parent) is + considered to be the the owner of the return value (the child). + pybind11 then couples the lifetime of the parent to the child via a + reference relationship that ensures that the parent cannot be garbage + collected while Python is still using the child. More advanced + variations of this scheme are also possible using combinations of + return_value_policy::reference and the keep_alive call policy */ + reference_internal +}; + +NAMESPACE_BEGIN(detail) + +inline static constexpr int log2(size_t n, int k = 0) { return (n <= 1) ? k : log2(n >> 1, k + 1); } + +// Returns the size as a multiple of sizeof(void *), rounded up. +inline static constexpr size_t size_in_ptrs(size_t s) { return 1 + ((s - 1) >> log2(sizeof(void *))); } + +/** + * The space to allocate for simple layout instance holders (see below) in multiple of the size of + * a pointer (e.g. 2 means 16 bytes on 64-bit architectures). The default is the minimum required + * to holder either a std::unique_ptr or std::shared_ptr (which is almost always + * sizeof(std::shared_ptr<T>)). + */ +constexpr size_t instance_simple_holder_in_ptrs() { + static_assert(sizeof(std::shared_ptr<int>) >= sizeof(std::unique_ptr<int>), + "pybind assumes std::shared_ptrs are at least as big as std::unique_ptrs"); + return size_in_ptrs(sizeof(std::shared_ptr<int>)); +} + +// Forward declarations +struct type_info; +struct value_and_holder; + +/// The 'instance' type which needs to be standard layout (need to be able to use 'offsetof') +struct instance { + PyObject_HEAD + /// Storage for pointers and holder; see simple_layout, below, for a description + union { + void *simple_value_holder[1 + instance_simple_holder_in_ptrs()]; + struct { + void **values_and_holders; + uint8_t *status; + } nonsimple; + }; + /// Weak references (needed for keep alive): + PyObject *weakrefs; + /// If true, the pointer is owned which means we're free to manage it with a holder. + bool owned : 1; + /** + * An instance has two possible value/holder layouts. + * + * Simple layout (when this flag is true), means the `simple_value_holder` is set with a pointer + * and the holder object governing that pointer, i.e. [val1*][holder]. This layout is applied + * whenever there is no python-side multiple inheritance of bound C++ types *and* the type's + * holder will fit in the default space (which is large enough to hold either a std::unique_ptr + * or std::shared_ptr). + * + * Non-simple layout applies when using custom holders that require more space than `shared_ptr` + * (which is typically the size of two pointers), or when multiple inheritance is used on the + * python side. Non-simple layout allocates the required amount of memory to have multiple + * bound C++ classes as parents. Under this layout, `nonsimple.values_and_holders` is set to a + * pointer to allocated space of the required space to hold a a sequence of value pointers and + * holders followed `status`, a set of bit flags (1 byte each), i.e. + * [val1*][holder1][val2*][holder2]...[bb...] where each [block] is rounded up to a multiple of + * `sizeof(void *)`. `nonsimple.holder_constructed` is, for convenience, a pointer to the + * beginning of the [bb...] block (but not independently allocated). + * + * Status bits indicate whether the associated holder is constructed (& + * status_holder_constructed) and whether the value pointer is registered (& + * status_instance_registered) in `registered_instances`. + */ + bool simple_layout : 1; + /// For simple layout, tracks whether the holder has been constructed + bool simple_holder_constructed : 1; + /// For simple layout, tracks whether the instance is registered in `registered_instances` + bool simple_instance_registered : 1; + /// If true, get_internals().patients has an entry for this object + bool has_patients : 1; + + /// Initializes all of the above type/values/holders data (but not the instance values themselves) + void allocate_layout(); + + /// Destroys/deallocates all of the above + void deallocate_layout(); + + /// Returns the value_and_holder wrapper for the given type (or the first, if `find_type` + /// omitted). Returns a default-constructed (with `.inst = nullptr`) object on failure if + /// `throw_if_missing` is false. + value_and_holder get_value_and_holder(const type_info *find_type = nullptr, bool throw_if_missing = true); + + /// Bit values for the non-simple status flags + static constexpr uint8_t status_holder_constructed = 1; + static constexpr uint8_t status_instance_registered = 2; +}; + +static_assert(std::is_standard_layout<instance>::value, "Internal error: `pybind11::detail::instance` is not standard layout!"); + +/// from __cpp_future__ import (convenient aliases from C++14/17) +#if defined(PYBIND11_CPP14) && (!defined(_MSC_VER) || _MSC_VER >= 1910) +using std::enable_if_t; +using std::conditional_t; +using std::remove_cv_t; +using std::remove_reference_t; +#else +template <bool B, typename T = void> using enable_if_t = typename std::enable_if<B, T>::type; +template <bool B, typename T, typename F> using conditional_t = typename std::conditional<B, T, F>::type; +template <typename T> using remove_cv_t = typename std::remove_cv<T>::type; +template <typename T> using remove_reference_t = typename std::remove_reference<T>::type; +#endif + +/// Index sequences +#if defined(PYBIND11_CPP14) +using std::index_sequence; +using std::make_index_sequence; +#else +template<size_t ...> struct index_sequence { }; +template<size_t N, size_t ...S> struct make_index_sequence_impl : make_index_sequence_impl <N - 1, N - 1, S...> { }; +template<size_t ...S> struct make_index_sequence_impl <0, S...> { typedef index_sequence<S...> type; }; +template<size_t N> using make_index_sequence = typename make_index_sequence_impl<N>::type; +#endif + +/// Make an index sequence of the indices of true arguments +template <typename ISeq, size_t, bool...> struct select_indices_impl { using type = ISeq; }; +template <size_t... IPrev, size_t I, bool B, bool... Bs> struct select_indices_impl<index_sequence<IPrev...>, I, B, Bs...> + : select_indices_impl<conditional_t<B, index_sequence<IPrev..., I>, index_sequence<IPrev...>>, I + 1, Bs...> {}; +template <bool... Bs> using select_indices = typename select_indices_impl<index_sequence<>, 0, Bs...>::type; + +/// Backports of std::bool_constant and std::negation to accomodate older compilers +template <bool B> using bool_constant = std::integral_constant<bool, B>; +template <typename T> struct negation : bool_constant<!T::value> { }; + +template <typename...> struct void_t_impl { using type = void; }; +template <typename... Ts> using void_t = typename void_t_impl<Ts...>::type; + +/// Compile-time all/any/none of that check the boolean value of all template types +#ifdef __cpp_fold_expressions +template <class... Ts> using all_of = bool_constant<(Ts::value && ...)>; +template <class... Ts> using any_of = bool_constant<(Ts::value || ...)>; +#elif !defined(_MSC_VER) +template <bool...> struct bools {}; +template <class... Ts> using all_of = std::is_same< + bools<Ts::value..., true>, + bools<true, Ts::value...>>; +template <class... Ts> using any_of = negation<all_of<negation<Ts>...>>; +#else +// MSVC has trouble with the above, but supports std::conjunction, which we can use instead (albeit +// at a slight loss of compilation efficiency). +template <class... Ts> using all_of = std::conjunction<Ts...>; +template <class... Ts> using any_of = std::disjunction<Ts...>; +#endif +template <class... Ts> using none_of = negation<any_of<Ts...>>; + +template <class T, template<class> class... Predicates> using satisfies_all_of = all_of<Predicates<T>...>; +template <class T, template<class> class... Predicates> using satisfies_any_of = any_of<Predicates<T>...>; +template <class T, template<class> class... Predicates> using satisfies_none_of = none_of<Predicates<T>...>; + +/// Strip the class from a method type +template <typename T> struct remove_class { }; +template <typename C, typename R, typename... A> struct remove_class<R (C::*)(A...)> { typedef R type(A...); }; +template <typename C, typename R, typename... A> struct remove_class<R (C::*)(A...) const> { typedef R type(A...); }; + +/// Helper template to strip away type modifiers +template <typename T> struct intrinsic_type { typedef T type; }; +template <typename T> struct intrinsic_type<const T> { typedef typename intrinsic_type<T>::type type; }; +template <typename T> struct intrinsic_type<T*> { typedef typename intrinsic_type<T>::type type; }; +template <typename T> struct intrinsic_type<T&> { typedef typename intrinsic_type<T>::type type; }; +template <typename T> struct intrinsic_type<T&&> { typedef typename intrinsic_type<T>::type type; }; +template <typename T, size_t N> struct intrinsic_type<const T[N]> { typedef typename intrinsic_type<T>::type type; }; +template <typename T, size_t N> struct intrinsic_type<T[N]> { typedef typename intrinsic_type<T>::type type; }; +template <typename T> using intrinsic_t = typename intrinsic_type<T>::type; + +/// Helper type to replace 'void' in some expressions +struct void_type { }; + +/// Helper template which holds a list of types +template <typename...> struct type_list { }; + +/// Compile-time integer sum +#ifdef __cpp_fold_expressions +template <typename... Ts> constexpr size_t constexpr_sum(Ts... ns) { return (0 + ... + size_t{ns}); } +#else +constexpr size_t constexpr_sum() { return 0; } +template <typename T, typename... Ts> +constexpr size_t constexpr_sum(T n, Ts... ns) { return size_t{n} + constexpr_sum(ns...); } +#endif + +NAMESPACE_BEGIN(constexpr_impl) +/// Implementation details for constexpr functions +constexpr int first(int i) { return i; } +template <typename T, typename... Ts> +constexpr int first(int i, T v, Ts... vs) { return v ? i : first(i + 1, vs...); } + +constexpr int last(int /*i*/, int result) { return result; } +template <typename T, typename... Ts> +constexpr int last(int i, int result, T v, Ts... vs) { return last(i + 1, v ? i : result, vs...); } +NAMESPACE_END(constexpr_impl) + +/// Return the index of the first type in Ts which satisfies Predicate<T>. Returns sizeof...(Ts) if +/// none match. +template <template<typename> class Predicate, typename... Ts> +constexpr int constexpr_first() { return constexpr_impl::first(0, Predicate<Ts>::value...); } + +/// Return the index of the last type in Ts which satisfies Predicate<T>, or -1 if none match. +template <template<typename> class Predicate, typename... Ts> +constexpr int constexpr_last() { return constexpr_impl::last(0, -1, Predicate<Ts>::value...); } + +/// Return the Nth element from the parameter pack +template <size_t N, typename T, typename... Ts> +struct pack_element { using type = typename pack_element<N - 1, Ts...>::type; }; +template <typename T, typename... Ts> +struct pack_element<0, T, Ts...> { using type = T; }; + +/// Return the one and only type which matches the predicate, or Default if none match. +/// If more than one type matches the predicate, fail at compile-time. +template <template<typename> class Predicate, typename Default, typename... Ts> +struct exactly_one { + static constexpr auto found = constexpr_sum(Predicate<Ts>::value...); + static_assert(found <= 1, "Found more than one type matching the predicate"); + + static constexpr auto index = found ? constexpr_first<Predicate, Ts...>() : 0; + using type = conditional_t<found, typename pack_element<index, Ts...>::type, Default>; +}; +template <template<typename> class P, typename Default> +struct exactly_one<P, Default> { using type = Default; }; + +template <template<typename> class Predicate, typename Default, typename... Ts> +using exactly_one_t = typename exactly_one<Predicate, Default, Ts...>::type; + +/// Defer the evaluation of type T until types Us are instantiated +template <typename T, typename... /*Us*/> struct deferred_type { using type = T; }; +template <typename T, typename... Us> using deferred_t = typename deferred_type<T, Us...>::type; + +/// Like is_base_of, but requires a strict base (i.e. `is_strict_base_of<T, T>::value == false`, +/// unlike `std::is_base_of`) +template <typename Base, typename Derived> using is_strict_base_of = bool_constant< + std::is_base_of<Base, Derived>::value && !std::is_same<Base, Derived>::value>; + +template <template<typename...> class Base> +struct is_template_base_of_impl { + template <typename... Us> static std::true_type check(Base<Us...> *); + static std::false_type check(...); +}; + +/// Check if a template is the base of a type. For example: +/// `is_template_base_of<Base, T>` is true if `struct T : Base<U> {}` where U can be anything +template <template<typename...> class Base, typename T> +#if !defined(_MSC_VER) +using is_template_base_of = decltype(is_template_base_of_impl<Base>::check((intrinsic_t<T>*)nullptr)); +#else // MSVC2015 has trouble with decltype in template aliases +struct is_template_base_of : decltype(is_template_base_of_impl<Base>::check((intrinsic_t<T>*)nullptr)) { }; +#endif + +/// Check if T is an instantiation of the template `Class`. For example: +/// `is_instantiation<shared_ptr, T>` is true if `T == shared_ptr<U>` where U can be anything. +template <template<typename...> class Class, typename T> +struct is_instantiation : std::false_type { }; +template <template<typename...> class Class, typename... Us> +struct is_instantiation<Class, Class<Us...>> : std::true_type { }; + +/// Check if T is std::shared_ptr<U> where U can be anything +template <typename T> using is_shared_ptr = is_instantiation<std::shared_ptr, T>; + +/// Check if T looks like an input iterator +template <typename T, typename = void> struct is_input_iterator : std::false_type {}; +template <typename T> +struct is_input_iterator<T, void_t<decltype(*std::declval<T &>()), decltype(++std::declval<T &>())>> + : std::true_type {}; + +template <typename T> using is_function_pointer = bool_constant< + std::is_pointer<T>::value && std::is_function<typename std::remove_pointer<T>::type>::value>; + +template <typename F> struct strip_function_object { + using type = typename remove_class<decltype(&F::operator())>::type; +}; + +// Extracts the function signature from a function, function pointer or lambda. +template <typename Function, typename F = remove_reference_t<Function>> +using function_signature_t = conditional_t< + std::is_function<F>::value, + F, + typename conditional_t< + std::is_pointer<F>::value || std::is_member_pointer<F>::value, + std::remove_pointer<F>, + strip_function_object<F> + >::type +>; + +/// Returns true if the type looks like a lambda: that is, isn't a function, pointer or member +/// pointer. Note that this can catch all sorts of other things, too; this is intended to be used +/// in a place where passing a lambda makes sense. +template <typename T> using is_lambda = satisfies_none_of<remove_reference_t<T>, + std::is_function, std::is_pointer, std::is_member_pointer>; + +/// Ignore that a variable is unused in compiler warnings +inline void ignore_unused(const int *) { } + +/// Apply a function over each element of a parameter pack +#ifdef __cpp_fold_expressions +#define PYBIND11_EXPAND_SIDE_EFFECTS(PATTERN) (((PATTERN), void()), ...) +#else +using expand_side_effects = bool[]; +#define PYBIND11_EXPAND_SIDE_EFFECTS(PATTERN) pybind11::detail::expand_side_effects{ ((PATTERN), void(), false)..., false } +#endif + +NAMESPACE_END(detail) + +/// C++ bindings of builtin Python exceptions +class builtin_exception : public std::runtime_error { +public: + using std::runtime_error::runtime_error; + /// Set the error using the Python C API + virtual void set_error() const = 0; +}; + +#define PYBIND11_RUNTIME_EXCEPTION(name, type) \ + class name : public builtin_exception { public: \ + using builtin_exception::builtin_exception; \ + name() : name("") { } \ + void set_error() const override { PyErr_SetString(type, what()); } \ + }; + +PYBIND11_RUNTIME_EXCEPTION(stop_iteration, PyExc_StopIteration) +PYBIND11_RUNTIME_EXCEPTION(index_error, PyExc_IndexError) +PYBIND11_RUNTIME_EXCEPTION(key_error, PyExc_KeyError) +PYBIND11_RUNTIME_EXCEPTION(value_error, PyExc_ValueError) +PYBIND11_RUNTIME_EXCEPTION(type_error, PyExc_TypeError) +PYBIND11_RUNTIME_EXCEPTION(cast_error, PyExc_RuntimeError) /// Thrown when pybind11::cast or handle::call fail due to a type casting error +PYBIND11_RUNTIME_EXCEPTION(reference_cast_error, PyExc_RuntimeError) /// Used internally + +[[noreturn]] PYBIND11_NOINLINE inline void pybind11_fail(const char *reason) { throw std::runtime_error(reason); } +[[noreturn]] PYBIND11_NOINLINE inline void pybind11_fail(const std::string &reason) { throw std::runtime_error(reason); } + +template <typename T, typename SFINAE = void> struct format_descriptor { }; + +NAMESPACE_BEGIN(detail) +// Returns the index of the given type in the type char array below, and in the list in numpy.h +// The order here is: bool; 8 ints ((signed,unsigned)x(8,16,32,64)bits); float,double,long double; +// complex float,double,long double. Note that the long double types only participate when long +// double is actually longer than double (it isn't under MSVC). +// NB: not only the string below but also complex.h and numpy.h rely on this order. +template <typename T, typename SFINAE = void> struct is_fmt_numeric { static constexpr bool value = false; }; +template <typename T> struct is_fmt_numeric<T, enable_if_t<std::is_arithmetic<T>::value>> { + static constexpr bool value = true; + static constexpr int index = std::is_same<T, bool>::value ? 0 : 1 + ( + std::is_integral<T>::value ? detail::log2(sizeof(T))*2 + std::is_unsigned<T>::value : 8 + ( + std::is_same<T, double>::value ? 1 : std::is_same<T, long double>::value ? 2 : 0)); +}; +NAMESPACE_END(detail) + +template <typename T> struct format_descriptor<T, detail::enable_if_t<std::is_arithmetic<T>::value>> { + static constexpr const char c = "?bBhHiIqQfdg"[detail::is_fmt_numeric<T>::index]; + static constexpr const char value[2] = { c, '\0' }; + static std::string format() { return std::string(1, c); } +}; + +template <typename T> constexpr const char format_descriptor< + T, detail::enable_if_t<std::is_arithmetic<T>::value>>::value[2]; + +/// RAII wrapper that temporarily clears any Python error state +struct error_scope { + PyObject *type, *value, *trace; + error_scope() { PyErr_Fetch(&type, &value, &trace); } + ~error_scope() { PyErr_Restore(type, value, trace); } +}; + +/// Dummy destructor wrapper that can be used to expose classes with a private destructor +struct nodelete { template <typename T> void operator()(T*) { } }; + +// overload_cast requires variable templates: C++14 +#if defined(PYBIND11_CPP14) +#define PYBIND11_OVERLOAD_CAST 1 + +NAMESPACE_BEGIN(detail) +template <typename... Args> +struct overload_cast_impl { + constexpr overload_cast_impl() {} // MSVC 2015 needs this + + template <typename Return> + constexpr auto operator()(Return (*pf)(Args...)) const noexcept + -> decltype(pf) { return pf; } + + template <typename Return, typename Class> + constexpr auto operator()(Return (Class::*pmf)(Args...), std::false_type = {}) const noexcept + -> decltype(pmf) { return pmf; } + + template <typename Return, typename Class> + constexpr auto operator()(Return (Class::*pmf)(Args...) const, std::true_type) const noexcept + -> decltype(pmf) { return pmf; } +}; +NAMESPACE_END(detail) + +/// Syntax sugar for resolving overloaded function pointers: +/// - regular: static_cast<Return (Class::*)(Arg0, Arg1, Arg2)>(&Class::func) +/// - sweet: overload_cast<Arg0, Arg1, Arg2>(&Class::func) +template <typename... Args> +static constexpr detail::overload_cast_impl<Args...> overload_cast = {}; +// MSVC 2015 only accepts this particular initialization syntax for this variable template. + +/// Const member function selector for overload_cast +/// - regular: static_cast<Return (Class::*)(Arg) const>(&Class::func) +/// - sweet: overload_cast<Arg>(&Class::func, const_) +static constexpr auto const_ = std::true_type{}; + +#else // no overload_cast: providing something that static_assert-fails: +template <typename... Args> struct overload_cast { + static_assert(detail::deferred_t<std::false_type, Args...>::value, + "pybind11::overload_cast<...> requires compiling in C++14 mode"); +}; +#endif // overload_cast + +NAMESPACE_BEGIN(detail) + +// Adaptor for converting arbitrary container arguments into a vector; implicitly convertible from +// any standard container (or C-style array) supporting std::begin/std::end, any singleton +// arithmetic type (if T is arithmetic), or explicitly constructible from an iterator pair. +template <typename T> +class any_container { + std::vector<T> v; +public: + any_container() = default; + + // Can construct from a pair of iterators + template <typename It, typename = enable_if_t<is_input_iterator<It>::value>> + any_container(It first, It last) : v(first, last) { } + + // Implicit conversion constructor from any arbitrary container type with values convertible to T + template <typename Container, typename = enable_if_t<std::is_convertible<decltype(*std::begin(std::declval<const Container &>())), T>::value>> + any_container(const Container &c) : any_container(std::begin(c), std::end(c)) { } + + // initializer_list's aren't deducible, so don't get matched by the above template; we need this + // to explicitly allow implicit conversion from one: + template <typename TIn, typename = enable_if_t<std::is_convertible<TIn, T>::value>> + any_container(const std::initializer_list<TIn> &c) : any_container(c.begin(), c.end()) { } + + // Avoid copying if given an rvalue vector of the correct type. + any_container(std::vector<T> &&v) : v(std::move(v)) { } + + // Moves the vector out of an rvalue any_container + operator std::vector<T> &&() && { return std::move(v); } + + // Dereferencing obtains a reference to the underlying vector + std::vector<T> &operator*() { return v; } + const std::vector<T> &operator*() const { return v; } + + // -> lets you call methods on the underlying vector + std::vector<T> *operator->() { return &v; } + const std::vector<T> *operator->() const { return &v; } +}; + +NAMESPACE_END(detail) + + + +NAMESPACE_END(PYBIND11_NAMESPACE) diff --git a/ext/pybind11/include/pybind11/descr.h b/ext/pybind11/include/pybind11/detail/descr.h index 2c3fb3d13..e3bf2ba97 100644 --- a/ext/pybind11/include/pybind11/descr.h +++ b/ext/pybind11/include/pybind11/detail/descr.h @@ -1,5 +1,5 @@ /* - pybind11/descr.h: Helper type for concatenating type signatures + pybind11/detail/descr.h: Helper type for concatenating type signatures either at runtime (C++11) or compile time (C++14) Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch> @@ -12,10 +12,12 @@ #include "common.h" -NAMESPACE_BEGIN(pybind11) +NAMESPACE_BEGIN(PYBIND11_NAMESPACE) NAMESPACE_BEGIN(detail) -#if defined(PYBIND11_CPP14) /* Concatenate type signatures at compile time using C++14 */ +/* Concatenate type signatures at compile time using C++14 */ +#if defined(PYBIND11_CPP14) && !defined(_MSC_VER) +#define PYBIND11_CONSTEXPR_DESCR template <size_t Size1, size_t Size2> class descr { template <size_t Size1_, size_t Size2_> friend class descr; @@ -113,20 +115,20 @@ public: memcpy(m_types, types, nTypes * sizeof(const std::type_info *)); } - PYBIND11_NOINLINE descr friend operator+(descr &&d1, descr &&d2) { + PYBIND11_NOINLINE descr operator+(descr &&d2) && { descr r; - size_t nChars1 = len(d1.m_text), nTypes1 = len(d1.m_types); + size_t nChars1 = len(m_text), nTypes1 = len(m_types); size_t nChars2 = len(d2.m_text), nTypes2 = len(d2.m_types); r.m_text = new char[nChars1 + nChars2 - 1]; r.m_types = new const std::type_info *[nTypes1 + nTypes2 - 1]; - memcpy(r.m_text, d1.m_text, (nChars1-1) * sizeof(char)); + memcpy(r.m_text, m_text, (nChars1-1) * sizeof(char)); memcpy(r.m_text + nChars1 - 1, d2.m_text, nChars2 * sizeof(char)); - memcpy(r.m_types, d1.m_types, (nTypes1-1) * sizeof(std::type_info *)); + memcpy(r.m_types, m_types, (nTypes1-1) * sizeof(std::type_info *)); memcpy(r.m_types + nTypes1 - 1, d2.m_types, nTypes2 * sizeof(std::type_info *)); - delete[] d1.m_text; delete[] d1.m_types; + delete[] m_text; delete[] m_types; delete[] d2.m_text; delete[] d2.m_types; return r; @@ -180,4 +182,4 @@ PYBIND11_NOINLINE inline descr type_descr(descr&& d) { return _("{") + std::move #endif NAMESPACE_END(detail) -NAMESPACE_END(pybind11) +NAMESPACE_END(PYBIND11_NAMESPACE) diff --git a/ext/pybind11/include/pybind11/detail/init.h b/ext/pybind11/include/pybind11/detail/init.h new file mode 100644 index 000000000..c3594a190 --- /dev/null +++ b/ext/pybind11/include/pybind11/detail/init.h @@ -0,0 +1,325 @@ +/* + pybind11/detail/init.h: init factory function implementation and support code. + + Copyright (c) 2017 Jason Rhinelander <jason@imaginary.ca> + + All rights reserved. Use of this source code is governed by a + BSD-style license that can be found in the LICENSE file. +*/ + +#pragma once + +#include "class.h" + +NAMESPACE_BEGIN(PYBIND11_NAMESPACE) +NAMESPACE_BEGIN(detail) + +template <> +class type_caster<value_and_holder> { +public: + bool load(handle h, bool) { + value = reinterpret_cast<value_and_holder *>(h.ptr()); + return true; + } + + template <typename> using cast_op_type = value_and_holder &; + operator value_and_holder &() { return *value; } + static PYBIND11_DESCR name() { return type_descr(_<value_and_holder>()); } + +private: + value_and_holder *value = nullptr; +}; + +NAMESPACE_BEGIN(initimpl) + +inline void no_nullptr(void *ptr) { + if (!ptr) throw type_error("pybind11::init(): factory function returned nullptr"); +} + +// Implementing functions for all forms of py::init<...> and py::init(...) +template <typename Class> using Cpp = typename Class::type; +template <typename Class> using Alias = typename Class::type_alias; +template <typename Class> using Holder = typename Class::holder_type; + +template <typename Class> using is_alias_constructible = std::is_constructible<Alias<Class>, Cpp<Class> &&>; + +// Takes a Cpp pointer and returns true if it actually is a polymorphic Alias instance. +template <typename Class, enable_if_t<Class::has_alias, int> = 0> +bool is_alias(Cpp<Class> *ptr) { + return dynamic_cast<Alias<Class> *>(ptr) != nullptr; +} +// Failing fallback version of the above for a no-alias class (always returns false) +template <typename /*Class*/> +constexpr bool is_alias(void *) { return false; } + +// Attempts to constructs an alias using a `Alias(Cpp &&)` constructor. This allows types with +// an alias to provide only a single Cpp factory function as long as the Alias can be +// constructed from an rvalue reference of the base Cpp type. This means that Alias classes +// can, when appropriate, simply define a `Alias(Cpp &&)` constructor rather than needing to +// inherit all the base class constructors. +template <typename Class> +void construct_alias_from_cpp(std::true_type /*is_alias_constructible*/, + value_and_holder &v_h, Cpp<Class> &&base) { + v_h.value_ptr() = new Alias<Class>(std::move(base)); +} +template <typename Class> +[[noreturn]] void construct_alias_from_cpp(std::false_type /*!is_alias_constructible*/, + value_and_holder &, Cpp<Class> &&) { + throw type_error("pybind11::init(): unable to convert returned instance to required " + "alias class: no `Alias<Class>(Class &&)` constructor available"); +} + +// Error-generating fallback for factories that don't match one of the below construction +// mechanisms. +template <typename Class> +void construct(...) { + static_assert(!std::is_same<Class, Class>::value /* always false */, + "pybind11::init(): init function must return a compatible pointer, " + "holder, or value"); +} + +// Pointer return v1: the factory function returns a class pointer for a registered class. +// If we don't need an alias (because this class doesn't have one, or because the final type is +// inherited on the Python side) we can simply take over ownership. Otherwise we need to try to +// construct an Alias from the returned base instance. +template <typename Class> +void construct(value_and_holder &v_h, Cpp<Class> *ptr, bool need_alias) { + no_nullptr(ptr); + if (Class::has_alias && need_alias && !is_alias<Class>(ptr)) { + // We're going to try to construct an alias by moving the cpp type. Whether or not + // that succeeds, we still need to destroy the original cpp pointer (either the + // moved away leftover, if the alias construction works, or the value itself if we + // throw an error), but we can't just call `delete ptr`: it might have a special + // deleter, or might be shared_from_this. So we construct a holder around it as if + // it was a normal instance, then steal the holder away into a local variable; thus + // the holder and destruction happens when we leave the C++ scope, and the holder + // class gets to handle the destruction however it likes. + v_h.value_ptr() = ptr; + v_h.set_instance_registered(true); // To prevent init_instance from registering it + v_h.type->init_instance(v_h.inst, nullptr); // Set up the holder + Holder<Class> temp_holder(std::move(v_h.holder<Holder<Class>>())); // Steal the holder + v_h.type->dealloc(v_h); // Destroys the moved-out holder remains, resets value ptr to null + v_h.set_instance_registered(false); + + construct_alias_from_cpp<Class>(is_alias_constructible<Class>{}, v_h, std::move(*ptr)); + } else { + // Otherwise the type isn't inherited, so we don't need an Alias + v_h.value_ptr() = ptr; + } +} + +// Pointer return v2: a factory that always returns an alias instance ptr. We simply take over +// ownership of the pointer. +template <typename Class, enable_if_t<Class::has_alias, int> = 0> +void construct(value_and_holder &v_h, Alias<Class> *alias_ptr, bool) { + no_nullptr(alias_ptr); + v_h.value_ptr() = static_cast<Cpp<Class> *>(alias_ptr); +} + +// Holder return: copy its pointer, and move or copy the returned holder into the new instance's +// holder. This also handles types like std::shared_ptr<T> and std::unique_ptr<T> where T is a +// derived type (through those holder's implicit conversion from derived class holder constructors). +template <typename Class> +void construct(value_and_holder &v_h, Holder<Class> holder, bool need_alias) { + auto *ptr = holder_helper<Holder<Class>>::get(holder); + // If we need an alias, check that the held pointer is actually an alias instance + if (Class::has_alias && need_alias && !is_alias<Class>(ptr)) + throw type_error("pybind11::init(): construction failed: returned holder-wrapped instance " + "is not an alias instance"); + + v_h.value_ptr() = ptr; + v_h.type->init_instance(v_h.inst, &holder); +} + +// return-by-value version 1: returning a cpp class by value. If the class has an alias and an +// alias is required the alias must have an `Alias(Cpp &&)` constructor so that we can construct +// the alias from the base when needed (i.e. because of Python-side inheritance). When we don't +// need it, we simply move-construct the cpp value into a new instance. +template <typename Class> +void construct(value_and_holder &v_h, Cpp<Class> &&result, bool need_alias) { + static_assert(std::is_move_constructible<Cpp<Class>>::value, + "pybind11::init() return-by-value factory function requires a movable class"); + if (Class::has_alias && need_alias) + construct_alias_from_cpp<Class>(is_alias_constructible<Class>{}, v_h, std::move(result)); + else + v_h.value_ptr() = new Cpp<Class>(std::move(result)); +} + +// return-by-value version 2: returning a value of the alias type itself. We move-construct an +// Alias instance (even if no the python-side inheritance is involved). The is intended for +// cases where Alias initialization is always desired. +template <typename Class> +void construct(value_and_holder &v_h, Alias<Class> &&result, bool) { + static_assert(std::is_move_constructible<Alias<Class>>::value, + "pybind11::init() return-by-alias-value factory function requires a movable alias class"); + v_h.value_ptr() = new Alias<Class>(std::move(result)); +} + +// Implementing class for py::init<...>() +template <typename... Args> +struct constructor { + template <typename Class, typename... Extra, enable_if_t<!Class::has_alias, int> = 0> + static void execute(Class &cl, const Extra&... extra) { + cl.def("__init__", [](value_and_holder &v_h, Args... args) { + v_h.value_ptr() = new Cpp<Class>{std::forward<Args>(args)...}; + }, is_new_style_constructor(), extra...); + } + + template <typename Class, typename... Extra, + enable_if_t<Class::has_alias && + std::is_constructible<Cpp<Class>, Args...>::value, int> = 0> + static void execute(Class &cl, const Extra&... extra) { + cl.def("__init__", [](value_and_holder &v_h, Args... args) { + if (Py_TYPE(v_h.inst) == v_h.type->type) + v_h.value_ptr() = new Cpp<Class>{std::forward<Args>(args)...}; + else + v_h.value_ptr() = new Alias<Class>{std::forward<Args>(args)...}; + }, is_new_style_constructor(), extra...); + } + + template <typename Class, typename... Extra, + enable_if_t<Class::has_alias && + !std::is_constructible<Cpp<Class>, Args...>::value, int> = 0> + static void execute(Class &cl, const Extra&... extra) { + cl.def("__init__", [](value_and_holder &v_h, Args... args) { + v_h.value_ptr() = new Alias<Class>{std::forward<Args>(args)...}; + }, is_new_style_constructor(), extra...); + } +}; + +// Implementing class for py::init_alias<...>() +template <typename... Args> struct alias_constructor { + template <typename Class, typename... Extra, + enable_if_t<Class::has_alias && std::is_constructible<Alias<Class>, Args...>::value, int> = 0> + static void execute(Class &cl, const Extra&... extra) { + cl.def("__init__", [](value_and_holder &v_h, Args... args) { + v_h.value_ptr() = new Alias<Class>{std::forward<Args>(args)...}; + }, is_new_style_constructor(), extra...); + } +}; + +// Implementation class for py::init(Func) and py::init(Func, AliasFunc) +template <typename CFunc, typename AFunc = void_type (*)(), + typename = function_signature_t<CFunc>, typename = function_signature_t<AFunc>> +struct factory; + +// Specialization for py::init(Func) +template <typename Func, typename Return, typename... Args> +struct factory<Func, void_type (*)(), Return(Args...)> { + remove_reference_t<Func> class_factory; + + factory(Func &&f) : class_factory(std::forward<Func>(f)) { } + + // The given class either has no alias or has no separate alias factory; + // this always constructs the class itself. If the class is registered with an alias + // type and an alias instance is needed (i.e. because the final type is a Python class + // inheriting from the C++ type) the returned value needs to either already be an alias + // instance, or the alias needs to be constructible from a `Class &&` argument. + template <typename Class, typename... Extra> + void execute(Class &cl, const Extra &...extra) && { + #if defined(PYBIND11_CPP14) + cl.def("__init__", [func = std::move(class_factory)] + #else + auto &func = class_factory; + cl.def("__init__", [func] + #endif + (value_and_holder &v_h, Args... args) { + construct<Class>(v_h, func(std::forward<Args>(args)...), + Py_TYPE(v_h.inst) != v_h.type->type); + }, is_new_style_constructor(), extra...); + } +}; + +// Specialization for py::init(Func, AliasFunc) +template <typename CFunc, typename AFunc, + typename CReturn, typename... CArgs, typename AReturn, typename... AArgs> +struct factory<CFunc, AFunc, CReturn(CArgs...), AReturn(AArgs...)> { + static_assert(sizeof...(CArgs) == sizeof...(AArgs), + "pybind11::init(class_factory, alias_factory): class and alias factories " + "must have identical argument signatures"); + static_assert(all_of<std::is_same<CArgs, AArgs>...>::value, + "pybind11::init(class_factory, alias_factory): class and alias factories " + "must have identical argument signatures"); + + remove_reference_t<CFunc> class_factory; + remove_reference_t<AFunc> alias_factory; + + factory(CFunc &&c, AFunc &&a) + : class_factory(std::forward<CFunc>(c)), alias_factory(std::forward<AFunc>(a)) { } + + // The class factory is called when the `self` type passed to `__init__` is the direct + // class (i.e. not inherited), the alias factory when `self` is a Python-side subtype. + template <typename Class, typename... Extra> + void execute(Class &cl, const Extra&... extra) && { + static_assert(Class::has_alias, "The two-argument version of `py::init()` can " + "only be used if the class has an alias"); + #if defined(PYBIND11_CPP14) + cl.def("__init__", [class_func = std::move(class_factory), alias_func = std::move(alias_factory)] + #else + auto &class_func = class_factory; + auto &alias_func = alias_factory; + cl.def("__init__", [class_func, alias_func] + #endif + (value_and_holder &v_h, CArgs... args) { + if (Py_TYPE(v_h.inst) == v_h.type->type) + // If the instance type equals the registered type we don't have inheritance, so + // don't need the alias and can construct using the class function: + construct<Class>(v_h, class_func(std::forward<CArgs>(args)...), false); + else + construct<Class>(v_h, alias_func(std::forward<CArgs>(args)...), true); + }, is_new_style_constructor(), extra...); + } +}; + +/// Set just the C++ state. Same as `__init__`. +template <typename Class, typename T> +void setstate(value_and_holder &v_h, T &&result, bool need_alias) { + construct<Class>(v_h, std::forward<T>(result), need_alias); +} + +/// Set both the C++ and Python states +template <typename Class, typename T, typename O, + enable_if_t<std::is_convertible<O, handle>::value, int> = 0> +void setstate(value_and_holder &v_h, std::pair<T, O> &&result, bool need_alias) { + construct<Class>(v_h, std::move(result.first), need_alias); + setattr((PyObject *) v_h.inst, "__dict__", result.second); +} + +/// Implementation for py::pickle(GetState, SetState) +template <typename Get, typename Set, + typename = function_signature_t<Get>, typename = function_signature_t<Set>> +struct pickle_factory; + +template <typename Get, typename Set, + typename RetState, typename Self, typename NewInstance, typename ArgState> +struct pickle_factory<Get, Set, RetState(Self), NewInstance(ArgState)> { + static_assert(std::is_same<intrinsic_t<RetState>, intrinsic_t<ArgState>>::value, + "The type returned by `__getstate__` must be the same " + "as the argument accepted by `__setstate__`"); + + remove_reference_t<Get> get; + remove_reference_t<Set> set; + + pickle_factory(Get get, Set set) + : get(std::forward<Get>(get)), set(std::forward<Set>(set)) { } + + template <typename Class, typename... Extra> + void execute(Class &cl, const Extra &...extra) && { + cl.def("__getstate__", std::move(get)); + +#if defined(PYBIND11_CPP14) + cl.def("__setstate__", [func = std::move(set)] +#else + auto &func = set; + cl.def("__setstate__", [func] +#endif + (value_and_holder &v_h, ArgState state) { + setstate<Class>(v_h, func(std::forward<ArgState>(state)), + Py_TYPE(v_h.inst) != v_h.type->type); + }, is_new_style_constructor(), extra...); + } +}; + +NAMESPACE_END(initimpl) +NAMESPACE_END(detail) +NAMESPACE_END(pybind11) diff --git a/ext/pybind11/include/pybind11/detail/internals.h b/ext/pybind11/include/pybind11/detail/internals.h new file mode 100644 index 000000000..213cbaeb2 --- /dev/null +++ b/ext/pybind11/include/pybind11/detail/internals.h @@ -0,0 +1,247 @@ +/* + pybind11/detail/internals.h: Internal data structure and related functions + + Copyright (c) 2017 Wenzel Jakob <wenzel.jakob@epfl.ch> + + All rights reserved. Use of this source code is governed by a + BSD-style license that can be found in the LICENSE file. +*/ + +#pragma once + +#include "../pytypes.h" + +NAMESPACE_BEGIN(PYBIND11_NAMESPACE) +NAMESPACE_BEGIN(detail) +// Forward declarations +inline PyTypeObject *make_static_property_type(); +inline PyTypeObject *make_default_metaclass(); +inline PyObject *make_object_base_type(PyTypeObject *metaclass); + +// Python loads modules by default with dlopen with the RTLD_LOCAL flag; under libc++ and possibly +// other STLs, this means `typeid(A)` from one module won't equal `typeid(A)` from another module +// even when `A` is the same, non-hidden-visibility type (e.g. from a common include). Under +// libstdc++, this doesn't happen: equality and the type_index hash are based on the type name, +// which works. If not under a known-good stl, provide our own name-based hash and equality +// functions that use the type name. +#if defined(__GLIBCXX__) +inline bool same_type(const std::type_info &lhs, const std::type_info &rhs) { return lhs == rhs; } +using type_hash = std::hash<std::type_index>; +using type_equal_to = std::equal_to<std::type_index>; +#else +inline bool same_type(const std::type_info &lhs, const std::type_info &rhs) { + return lhs.name() == rhs.name() || std::strcmp(lhs.name(), rhs.name()) == 0; +} + +struct type_hash { + size_t operator()(const std::type_index &t) const { + size_t hash = 5381; + const char *ptr = t.name(); + while (auto c = static_cast<unsigned char>(*ptr++)) + hash = (hash * 33) ^ c; + return hash; + } +}; + +struct type_equal_to { + bool operator()(const std::type_index &lhs, const std::type_index &rhs) const { + return lhs.name() == rhs.name() || std::strcmp(lhs.name(), rhs.name()) == 0; + } +}; +#endif + +template <typename value_type> +using type_map = std::unordered_map<std::type_index, value_type, type_hash, type_equal_to>; + +struct overload_hash { + inline size_t operator()(const std::pair<const PyObject *, const char *>& v) const { + size_t value = std::hash<const void *>()(v.first); + value ^= std::hash<const void *>()(v.second) + 0x9e3779b9 + (value<<6) + (value>>2); + return value; + } +}; + +/// Internal data structure used to track registered instances and types. +/// Whenever binary incompatible changes are made to this structure, +/// `PYBIND11_INTERNALS_VERSION` must be incremented. +struct internals { + type_map<type_info *> registered_types_cpp; // std::type_index -> pybind11's type information + std::unordered_map<PyTypeObject *, std::vector<type_info *>> registered_types_py; // PyTypeObject* -> base type_info(s) + std::unordered_multimap<const void *, instance*> registered_instances; // void * -> instance* + std::unordered_set<std::pair<const PyObject *, const char *>, overload_hash> inactive_overload_cache; + type_map<std::vector<bool (*)(PyObject *, void *&)>> direct_conversions; + std::unordered_map<const PyObject *, std::vector<PyObject *>> patients; + std::forward_list<void (*) (std::exception_ptr)> registered_exception_translators; + std::unordered_map<std::string, void *> shared_data; // Custom data to be shared across extensions + std::vector<PyObject *> loader_patient_stack; // Used by `loader_life_support` + std::forward_list<std::string> static_strings; // Stores the std::strings backing detail::c_str() + PyTypeObject *static_property_type; + PyTypeObject *default_metaclass; + PyObject *instance_base; +#if defined(WITH_THREAD) + decltype(PyThread_create_key()) tstate = 0; // Usually an int but a long on Cygwin64 with Python 3.x + PyInterpreterState *istate = nullptr; +#endif +}; + +/// Additional type information which does not fit into the PyTypeObject. +/// Changes to this struct also require bumping `PYBIND11_INTERNALS_VERSION`. +struct type_info { + PyTypeObject *type; + const std::type_info *cpptype; + size_t type_size, holder_size_in_ptrs; + void *(*operator_new)(size_t); + void (*init_instance)(instance *, const void *); + void (*dealloc)(value_and_holder &v_h); + 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; + void *(*module_local_load)(PyObject *, const type_info *) = nullptr; + /* A simple type never occurs as a (direct or indirect) parent + * of a class that makes use of multiple inheritance */ + bool simple_type : 1; + /* True if there is no multiple inheritance in this type's inheritance tree */ + bool simple_ancestors : 1; + /* for base vs derived holder_type checks */ + bool default_holder : 1; + /* true if this is a type registered with py::module_local */ + bool module_local : 1; +}; + +/// Tracks the `internals` and `type_info` ABI version independent of the main library version +#define PYBIND11_INTERNALS_VERSION 1 + +#if defined(WITH_THREAD) +# define PYBIND11_INTERNALS_KIND "" +#else +# define PYBIND11_INTERNALS_KIND "_without_thread" +#endif + +#define PYBIND11_INTERNALS_ID "__pybind11_internals_v" \ + PYBIND11_TOSTRING(PYBIND11_INTERNALS_VERSION) PYBIND11_INTERNALS_KIND "__" + +#define PYBIND11_MODULE_LOCAL_ID "__pybind11_module_local_v" \ + PYBIND11_TOSTRING(PYBIND11_INTERNALS_VERSION) PYBIND11_INTERNALS_KIND "__" + +/// Each module locally stores a pointer to the `internals` data. The data +/// itself is shared among modules with the same `PYBIND11_INTERNALS_ID`. +inline internals *&get_internals_ptr() { + static internals *internals_ptr = nullptr; + return internals_ptr; +} + +/// Return a reference to the current `internals` data +PYBIND11_NOINLINE inline internals &get_internals() { + auto *&internals_ptr = get_internals_ptr(); + if (internals_ptr) + return *internals_ptr; + + constexpr auto *id = PYBIND11_INTERNALS_ID; + auto builtins = handle(PyEval_GetBuiltins()); + if (builtins.contains(id) && isinstance<capsule>(builtins[id])) { + internals_ptr = *static_cast<internals **>(capsule(builtins[id])); + + // We loaded builtins through python's builtins, which means that our `error_already_set` + // and `builtin_exception` may be different local classes than the ones set up in the + // initial exception translator, below, so add another for our local exception classes. + // + // libstdc++ doesn't require this (types there are identified only by name) +#if !defined(__GLIBCXX__) + 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; + } + } + ); +#endif + } 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; + } + } + ); + internals_ptr->static_property_type = make_static_property_type(); + internals_ptr->default_metaclass = make_default_metaclass(); + internals_ptr->instance_base = make_object_base_type(internals_ptr->default_metaclass); + } + return *internals_ptr; +} + +/// Works like `internals.registered_types_cpp`, but for module-local registered types: +inline type_map<type_info *> ®istered_local_types_cpp() { + static type_map<type_info *> locals{}; + return locals; +} + +/// Constructs a std::string with the given arguments, stores it in `internals`, and returns its +/// `c_str()`. Such strings objects have a long storage duration -- the internal strings are only +/// cleared when the program exits or after interpreter shutdown (when embedding), and so are +/// suitable for c-style strings needed by Python internals (such as PyTypeObject's tp_name). +template <typename... Args> +const char *c_str(Args &&...args) { + auto &strings = get_internals().static_strings; + strings.emplace_front(std::forward<Args>(args)...); + return strings.front().c_str(); +} + +NAMESPACE_END(detail) + +/// Returns a named pointer that is shared among all extension modules (using the same +/// pybind11 version) running in the current interpreter. Names starting with underscores +/// are reserved for internal usage. Returns `nullptr` if no matching entry was found. +inline PYBIND11_NOINLINE void *get_shared_data(const std::string &name) { + auto &internals = detail::get_internals(); + auto it = internals.shared_data.find(name); + return it != internals.shared_data.end() ? it->second : nullptr; +} + +/// Set the shared data that can be later recovered by `get_shared_data()`. +inline PYBIND11_NOINLINE void *set_shared_data(const std::string &name, void *data) { + detail::get_internals().shared_data[name] = data; + return data; +} + +/// Returns a typed reference to a shared data entry (by using `get_shared_data()`) if +/// such entry exists. Otherwise, a new object of default-constructible type `T` is +/// added to the shared data under the given name and a reference to it is returned. +template<typename T> +T &get_or_create_shared_data(const std::string &name) { + auto &internals = detail::get_internals(); + auto it = internals.shared_data.find(name); + T *ptr = (T *) (it != internals.shared_data.end() ? it->second : nullptr); + if (!ptr) { + ptr = new T(); + internals.shared_data[name] = ptr; + } + return *ptr; +} + +NAMESPACE_END(PYBIND11_NAMESPACE) diff --git a/ext/pybind11/include/pybind11/typeid.h b/ext/pybind11/include/pybind11/detail/typeid.h index c903fb14c..6f36aab75 100644 --- a/ext/pybind11/include/pybind11/typeid.h +++ b/ext/pybind11/include/pybind11/detail/typeid.h @@ -1,5 +1,5 @@ /* - pybind11/typeid.h: Compiler-independent access to type identifiers + pybind11/detail/typeid.h: Compiler-independent access to type identifiers Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch> @@ -16,7 +16,7 @@ #include <cxxabi.h> #endif -NAMESPACE_BEGIN(pybind11) +NAMESPACE_BEGIN(PYBIND11_NAMESPACE) NAMESPACE_BEGIN(detail) /// Erase all occurrences of a substring inline void erase_all(std::string &string, const std::string &search) { @@ -50,4 +50,4 @@ template <typename T> static std::string type_id() { return name; } -NAMESPACE_END(pybind11) +NAMESPACE_END(PYBIND11_NAMESPACE) diff --git a/ext/pybind11/include/pybind11/eigen.h b/ext/pybind11/include/pybind11/eigen.h index 6abe8c48f..a702bf39e 100644 --- a/ext/pybind11/include/pybind11/eigen.h +++ b/ext/pybind11/include/pybind11/eigen.h @@ -35,7 +35,7 @@ // of matrices seems highly undesirable. static_assert(EIGEN_VERSION_AT_LEAST(3,2,7), "Eigen support in pybind11 requires Eigen >= 3.2.7"); -NAMESPACE_BEGIN(pybind11) +NAMESPACE_BEGIN(PYBIND11_NAMESPACE) // Provide a convenience alias for easier pass-by-ref usage with fully dynamic strides: using EigenDStride = Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>; @@ -68,16 +68,22 @@ template <typename T> using is_eigen_other = all_of< template <bool EigenRowMajor> struct EigenConformable { bool conformable = false; EigenIndex rows = 0, cols = 0; - EigenDStride stride{0, 0}; + EigenDStride stride{0, 0}; // Only valid if negativestrides is false! + bool negativestrides = false; // If true, do not use stride! EigenConformable(bool fits = false) : conformable{fits} {} // Matrix type: EigenConformable(EigenIndex r, EigenIndex c, EigenIndex rstride, EigenIndex cstride) : - conformable{true}, rows{r}, cols{c}, - stride(EigenRowMajor ? rstride : cstride /* outer stride */, - EigenRowMajor ? cstride : rstride /* inner stride */) - {} + conformable{true}, rows{r}, cols{c} { + // TODO: when Eigen bug #747 is fixed, remove the tests for non-negativity. http://eigen.tuxfamily.org/bz/show_bug.cgi?id=747 + if (rstride < 0 || cstride < 0) { + negativestrides = true; + } else { + stride = {EigenRowMajor ? rstride : cstride /* outer stride */, + EigenRowMajor ? cstride : rstride /* inner stride */ }; + } + } // Vector type: EigenConformable(EigenIndex r, EigenIndex c, EigenIndex stride) : EigenConformable(r, c, r == 1 ? c*stride : stride, c == 1 ? r : r*stride) {} @@ -86,6 +92,7 @@ template <bool EigenRowMajor> struct EigenConformable { // To have compatible strides, we need (on both dimensions) one of fully dynamic strides, // matching strides, or a dimension size of 1 (in which case the stride value is irrelevant) return + !negativestrides && (props::inner_stride == Eigen::Dynamic || props::inner_stride == stride.inner() || (EigenRowMajor ? cols : rows) == 1) && (props::outer_stride == Eigen::Dynamic || props::outer_stride == stride.outer() || @@ -138,8 +145,8 @@ template <typename Type_> struct EigenProps { EigenIndex np_rows = a.shape(0), np_cols = a.shape(1), - np_rstride = a.strides(0) / sizeof(Scalar), - np_cstride = a.strides(1) / sizeof(Scalar); + np_rstride = a.strides(0) / static_cast<ssize_t>(sizeof(Scalar)), + np_cstride = a.strides(1) / static_cast<ssize_t>(sizeof(Scalar)); if ((fixed_rows && np_rows != rows) || (fixed_cols && np_cols != cols)) return false; @@ -149,7 +156,7 @@ template <typename Type_> struct EigenProps { // Otherwise we're storing an n-vector. Only one of the strides will be used, but whichever // is used, we want the (single) numpy stride value. const EigenIndex n = a.shape(0), - stride = a.strides(0) / sizeof(Scalar); + stride = a.strides(0) / static_cast<ssize_t>(sizeof(Scalar)); if (vector) { // Eigen type is a compile-time vector if (fixed && size != n) @@ -179,39 +186,35 @@ template <typename Type_> struct EigenProps { constexpr bool show_c_contiguous = show_order && requires_row_major; constexpr bool show_f_contiguous = !show_c_contiguous && show_order && requires_col_major; - return _("numpy.ndarray[") + npy_format_descriptor<Scalar>::name() + - _("[") + _<fixed_rows>(_<(size_t) rows>(), _("m")) + - _(", ") + _<fixed_cols>(_<(size_t) cols>(), _("n")) + - _("]") + - // For a reference type (e.g. Ref<MatrixXd>) we have other constraints that might need to be - // satisfied: writeable=True (for a mutable reference), and, depending on the map's stride - // options, possibly f_contiguous or c_contiguous. We include them in the descriptor output - // to provide some hint as to why a TypeError is occurring (otherwise it can be confusing to - // see that a function accepts a 'numpy.ndarray[float64[3,2]]' and an error message that you - // *gave* a numpy.ndarray of the right type and dimensions. - _<show_writeable>(", flags.writeable", "") + - _<show_c_contiguous>(", flags.c_contiguous", "") + - _<show_f_contiguous>(", flags.f_contiguous", "") + - _("]"); + return type_descr(_("numpy.ndarray[") + npy_format_descriptor<Scalar>::name() + + _("[") + _<fixed_rows>(_<(size_t) rows>(), _("m")) + + _(", ") + _<fixed_cols>(_<(size_t) cols>(), _("n")) + + _("]") + + // For a reference type (e.g. Ref<MatrixXd>) we have other constraints that might need to be + // satisfied: writeable=True (for a mutable reference), and, depending on the map's stride + // options, possibly f_contiguous or c_contiguous. We include them in the descriptor output + // to provide some hint as to why a TypeError is occurring (otherwise it can be confusing to + // see that a function accepts a 'numpy.ndarray[float64[3,2]]' and an error message that you + // *gave* a numpy.ndarray of the right type and dimensions. + _<show_writeable>(", flags.writeable", "") + + _<show_c_contiguous>(", flags.c_contiguous", "") + + _<show_f_contiguous>(", flags.f_contiguous", "") + + _("]") + ); } }; // Casts an Eigen type to numpy array. If given a base, the numpy array references the src data, // otherwise it'll make a copy. writeable lets you turn off the writeable flag for the array. template <typename props> handle eigen_array_cast(typename props::Type const &src, handle base = handle(), bool writeable = true) { - constexpr size_t elem_size = sizeof(typename props::Scalar); - std::vector<size_t> shape, strides; - if (props::vector) { - shape.push_back(src.size()); - strides.push_back(elem_size * src.innerStride()); - } - else { - shape.push_back(src.rows()); - shape.push_back(src.cols()); - strides.push_back(elem_size * src.rowStride()); - strides.push_back(elem_size * src.colStride()); - } - array a(std::move(shape), std::move(strides), src.data(), base); + constexpr ssize_t elem_size = sizeof(typename props::Scalar); + array a; + if (props::vector) + a = array({ src.size() }, { elem_size * src.innerStride() }, src.data(), base); + else + a = array({ src.rows(), src.cols() }, { elem_size * src.rowStride(), elem_size * src.colStride() }, + src.data(), base); + if (!writeable) array_proxy(a.ptr())->flags &= ~detail::npy_api::NPY_ARRAY_WRITEABLE_; @@ -246,8 +249,14 @@ struct type_caster<Type, enable_if_t<is_eigen_dense_plain<Type>::value>> { using Scalar = typename Type::Scalar; using props = EigenProps<Type>; - bool load(handle src, bool) { - auto buf = array_t<Scalar>::ensure(src); + bool load(handle src, bool convert) { + // If we're in no-convert mode, only load if given an array of the correct type + if (!convert && !isinstance<array_t<Scalar>>(src)) + return false; + + // Coerce into an array, but don't do type conversion yet; the copy below handles it. + auto buf = array::ensure(src); + if (!buf) return false; @@ -257,9 +266,19 @@ struct type_caster<Type, enable_if_t<is_eigen_dense_plain<Type>::value>> { auto fits = props::conformable(buf); if (!fits) - return false; // Non-comformable vector/matrix types + return false; + + // Allocate the new type, then build a numpy reference into it + value = Type(fits.rows, fits.cols); + auto ref = reinterpret_steal<array>(eigen_ref_array<props>(value)); + if (dims == 1) ref = ref.squeeze(); - value = Eigen::Map<const Type, 0, EigenDStride>(buf.data(), fits.rows, fits.cols, fits.stride); + int result = detail::npy_api::get().PyArray_CopyInto_(ref.ptr(), buf.ptr()); + + if (result < 0) { // Copy failed! + PyErr_Clear(); + return false; + } return true; } @@ -318,11 +337,12 @@ public: return cast_impl(src, policy, parent); } - static PYBIND11_DESCR name() { return type_descr(props::descriptor()); } + static PYBIND11_DESCR name() { return props::descriptor(); } operator Type*() { return &value; } operator Type&() { return value; } - template <typename T> using cast_op_type = cast_op_type<T>; + operator Type&&() && { return std::move(value); } + template <typename T> using cast_op_type = movable_cast_op_type<T>; private: Type value; @@ -442,6 +462,7 @@ public: if (!fits || !fits.template stride_compatible<props>()) return false; copy_or_ref = std::move(copy); + loader_life_support::add_patient(copy_or_ref); } ref.reset(); @@ -522,7 +543,7 @@ public: template<typename Type> struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> { typedef typename Type::Scalar Scalar; - typedef typename std::remove_reference<decltype(*std::declval<Type>().outerIndexPtr())>::type StorageIndex; + typedef remove_reference_t<decltype(*std::declval<Type>().outerIndexPtr())> StorageIndex; typedef typename Type::Index Index; static constexpr bool rowMajor = Type::IsRowMajor; @@ -535,7 +556,7 @@ struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> { object matrix_type = sparse_module.attr( rowMajor ? "csr_matrix" : "csc_matrix"); - if (obj.get_type() != matrix_type.ptr()) { + if (!obj.get_type().is(matrix_type)) { try { obj = matrix_type(obj); } catch (const error_already_set &) { @@ -565,9 +586,9 @@ struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> { object matrix_type = module::import("scipy.sparse").attr( rowMajor ? "csr_matrix" : "csc_matrix"); - array data((size_t) src.nonZeros(), src.valuePtr()); - array outerIndices((size_t) (rowMajor ? src.rows() : src.cols()) + 1, src.outerIndexPtr()); - array innerIndices((size_t) src.nonZeros(), src.innerIndexPtr()); + array data(src.nonZeros(), src.valuePtr()); + array outerIndices((rowMajor ? src.rows() : src.cols()) + 1, src.outerIndexPtr()); + array innerIndices(src.nonZeros(), src.innerIndexPtr()); return matrix_type( std::make_tuple(data, innerIndices, outerIndices), @@ -580,7 +601,7 @@ struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> { }; NAMESPACE_END(detail) -NAMESPACE_END(pybind11) +NAMESPACE_END(PYBIND11_NAMESPACE) #if defined(__GNUG__) || defined(__clang__) # pragma GCC diagnostic pop diff --git a/ext/pybind11/include/pybind11/embed.h b/ext/pybind11/include/pybind11/embed.h new file mode 100644 index 000000000..6664967c1 --- /dev/null +++ b/ext/pybind11/include/pybind11/embed.h @@ -0,0 +1,194 @@ +/* + pybind11/embed.h: Support for embedding the interpreter + + Copyright (c) 2017 Wenzel Jakob <wenzel.jakob@epfl.ch> + + All rights reserved. Use of this source code is governed by a + BSD-style license that can be found in the LICENSE file. +*/ + +#pragma once + +#include "pybind11.h" +#include "eval.h" + +#if defined(PYPY_VERSION) +# error Embedding the interpreter is not supported with PyPy +#endif + +#if PY_MAJOR_VERSION >= 3 +# define PYBIND11_EMBEDDED_MODULE_IMPL(name) \ + extern "C" PyObject *pybind11_init_impl_##name() { \ + return pybind11_init_wrapper_##name(); \ + } +#else +# define PYBIND11_EMBEDDED_MODULE_IMPL(name) \ + extern "C" void pybind11_init_impl_##name() { \ + pybind11_init_wrapper_##name(); \ + } +#endif + +/** \rst + Add a new module to the table of builtins for the interpreter. Must be + defined in global scope. The first macro parameter is the name of the + module (without quotes). The second parameter is the variable which will + be used as the interface to add functions and classes to the module. + + .. code-block:: cpp + + PYBIND11_EMBEDDED_MODULE(example, m) { + // ... initialize functions and classes here + m.def("foo", []() { + return "Hello, World!"; + }); + } + \endrst */ +#define PYBIND11_EMBEDDED_MODULE(name, variable) \ + static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \ + static PyObject PYBIND11_CONCAT(*pybind11_init_wrapper_, name)() { \ + auto m = pybind11::module(PYBIND11_TOSTRING(name)); \ + try { \ + PYBIND11_CONCAT(pybind11_init_, name)(m); \ + return m.ptr(); \ + } catch (pybind11::error_already_set &e) { \ + PyErr_SetString(PyExc_ImportError, e.what()); \ + return nullptr; \ + } catch (const std::exception &e) { \ + PyErr_SetString(PyExc_ImportError, e.what()); \ + return nullptr; \ + } \ + } \ + PYBIND11_EMBEDDED_MODULE_IMPL(name) \ + pybind11::detail::embedded_module name(PYBIND11_TOSTRING(name), \ + PYBIND11_CONCAT(pybind11_init_impl_, name)); \ + void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &variable) + + +NAMESPACE_BEGIN(PYBIND11_NAMESPACE) +NAMESPACE_BEGIN(detail) + +/// Python 2.7/3.x compatible version of `PyImport_AppendInittab` and error checks. +struct embedded_module { +#if PY_MAJOR_VERSION >= 3 + using init_t = PyObject *(*)(); +#else + using init_t = void (*)(); +#endif + embedded_module(const char *name, init_t init) { + if (Py_IsInitialized()) + pybind11_fail("Can't add new modules after the interpreter has been initialized"); + + auto result = PyImport_AppendInittab(name, init); + if (result == -1) + pybind11_fail("Insufficient memory to add a new module"); + } +}; + +NAMESPACE_END(detail) + +/** \rst + Initialize the Python interpreter. No other pybind11 or CPython API functions can be + called before this is done; with the exception of `PYBIND11_EMBEDDED_MODULE`. The + optional parameter can be used to skip the registration of signal handlers (see the + Python documentation for details). Calling this function again after the interpreter + has already been initialized is a fatal error. + \endrst */ +inline void initialize_interpreter(bool init_signal_handlers = true) { + if (Py_IsInitialized()) + pybind11_fail("The interpreter is already running"); + + Py_InitializeEx(init_signal_handlers ? 1 : 0); + + // Make .py files in the working directory available by default + module::import("sys").attr("path").cast<list>().append("."); +} + +/** \rst + Shut down the Python interpreter. No pybind11 or CPython API functions can be called + after this. In addition, pybind11 objects must not outlive the interpreter: + + .. code-block:: cpp + + { // BAD + py::initialize_interpreter(); + auto hello = py::str("Hello, World!"); + py::finalize_interpreter(); + } // <-- BOOM, hello's destructor is called after interpreter shutdown + + { // GOOD + py::initialize_interpreter(); + { // scoped + auto hello = py::str("Hello, World!"); + } // <-- OK, hello is cleaned up properly + py::finalize_interpreter(); + } + + { // BETTER + py::scoped_interpreter guard{}; + auto hello = py::str("Hello, World!"); + } + + .. warning:: + + The interpreter can be restarted by calling `initialize_interpreter` again. + Modules created using pybind11 can be safely re-initialized. However, Python + itself cannot completely unload binary extension modules and there are several + caveats with regard to interpreter restarting. All the details can be found + in the CPython documentation. In short, not all interpreter memory may be + freed, either due to reference cycles or user-created global data. + + \endrst */ +inline void finalize_interpreter() { + handle builtins(PyEval_GetBuiltins()); + const char *id = PYBIND11_INTERNALS_ID; + + // Get the internals pointer (without creating it if it doesn't exist). It's possible for the + // internals to be created during Py_Finalize() (e.g. if a py::capsule calls `get_internals()` + // during destruction), so we get the pointer-pointer here and check it after Py_Finalize(). + detail::internals **internals_ptr_ptr = &detail::get_internals_ptr(); + // It could also be stashed in builtins, so look there too: + if (builtins.contains(id) && isinstance<capsule>(builtins[id])) + internals_ptr_ptr = capsule(builtins[id]); + + Py_Finalize(); + + if (internals_ptr_ptr) { + delete *internals_ptr_ptr; + *internals_ptr_ptr = nullptr; + } +} + +/** \rst + Scope guard version of `initialize_interpreter` and `finalize_interpreter`. + This a move-only guard and only a single instance can exist. + + .. code-block:: cpp + + #include <pybind11/embed.h> + + int main() { + py::scoped_interpreter guard{}; + py::print(Hello, World!); + } // <-- interpreter shutdown + \endrst */ +class scoped_interpreter { +public: + scoped_interpreter(bool init_signal_handlers = true) { + initialize_interpreter(init_signal_handlers); + } + + scoped_interpreter(const scoped_interpreter &) = delete; + scoped_interpreter(scoped_interpreter &&other) noexcept { other.is_valid = false; } + scoped_interpreter &operator=(const scoped_interpreter &) = delete; + scoped_interpreter &operator=(scoped_interpreter &&) = delete; + + ~scoped_interpreter() { + if (is_valid) + finalize_interpreter(); + } + +private: + bool is_valid = true; +}; + +NAMESPACE_END(PYBIND11_NAMESPACE) diff --git a/ext/pybind11/include/pybind11/eval.h b/ext/pybind11/include/pybind11/eval.h index 5b2b98272..ea85ba1db 100644 --- a/ext/pybind11/include/pybind11/eval.h +++ b/ext/pybind11/include/pybind11/eval.h @@ -11,11 +11,9 @@ #pragma once -#pragma once - #include "pybind11.h" -NAMESPACE_BEGIN(pybind11) +NAMESPACE_BEGIN(PYBIND11_NAMESPACE) enum eval_mode { /// Evaluate a string containing an isolated expression @@ -29,12 +27,7 @@ enum eval_mode { }; template <eval_mode mode = eval_expr> -object eval(str expr, object global = object(), object local = object()) { - if (!global) { - global = reinterpret_borrow<object>(PyEval_GetGlobals()); - if (!global) - global = dict(); - } +object eval(str expr, object global = globals(), object local = object()) { if (!local) local = global; @@ -56,13 +49,25 @@ object eval(str expr, object global = object(), object local = object()) { return reinterpret_steal<object>(result); } +template <eval_mode mode = eval_expr, size_t N> +object eval(const char (&s)[N], object global = globals(), object local = object()) { + /* Support raw string literals by removing common leading whitespace */ + auto expr = (s[0] == '\n') ? str(module::import("textwrap").attr("dedent")(s)) + : str(s); + return eval<mode>(expr, global, local); +} + +inline void exec(str expr, object global = globals(), object local = object()) { + eval<eval_statements>(expr, global, local); +} + +template <size_t N> +void exec(const char (&s)[N], object global = globals(), object local = object()) { + eval<eval_statements>(s, global, local); +} + template <eval_mode mode = eval_statements> -object eval_file(str fname, object global = object(), object local = object()) { - if (!global) { - global = reinterpret_borrow<object>(PyEval_GetGlobals()); - if (!global) - global = dict(); - } +object eval_file(str fname, object global = globals(), object local = object()) { if (!local) local = global; @@ -109,4 +114,4 @@ object eval_file(str fname, object global = object(), object local = object()) { return reinterpret_steal<object>(result); } -NAMESPACE_END(pybind11) +NAMESPACE_END(PYBIND11_NAMESPACE) diff --git a/ext/pybind11/include/pybind11/functional.h b/ext/pybind11/include/pybind11/functional.h index a99ee737f..eda14ba58 100644 --- a/ext/pybind11/include/pybind11/functional.h +++ b/ext/pybind11/include/pybind11/functional.h @@ -12,7 +12,7 @@ #include "pybind11.h" #include <functional> -NAMESPACE_BEGIN(pybind11) +NAMESPACE_BEGIN(PYBIND11_NAMESPACE) NAMESPACE_BEGIN(detail) template <typename Return, typename... Args> @@ -22,14 +22,18 @@ struct type_caster<std::function<Return(Args...)>> { using function_type = Return (*) (Args...); public: - bool load(handle src_, bool) { - if (src_.is_none()) + bool load(handle src, bool convert) { + if (src.is_none()) { + // Defer accepting None to other overloads (if we aren't in convert mode): + if (!convert) return false; return true; + } - src_ = detail::get_function(src_); - if (!src_ || !PyCallable_Check(src_.ptr())) + if (!isinstance<function>(src)) return false; + auto func = reinterpret_borrow<function>(src); + /* When passing a C++ function as an argument to another C++ function via Python, every function call would normally involve @@ -38,21 +42,21 @@ public: stateless (i.e. function pointer or lambda function without captured variables), in which case the roundtrip can be avoided. */ - if (PyCFunction_Check(src_.ptr())) { - auto c = reinterpret_borrow<capsule>(PyCFunction_GET_SELF(src_.ptr())); + if (auto cfunc = func.cpp_function()) { + auto c = reinterpret_borrow<capsule>(PyCFunction_GET_SELF(cfunc.ptr())); auto rec = (function_record *) c; - if (rec && rec->is_stateless && rec->data[1] == &typeid(function_type)) { + if (rec && rec->is_stateless && + same_type(typeid(function_type), *reinterpret_cast<const std::type_info *>(rec->data[1]))) { struct capture { function_type f; }; value = ((capture *) &rec->data)->f; return true; } } - auto src = reinterpret_borrow<object>(src_); - value = [src](Args... args) -> Return { + value = [func](Args... args) -> Return { gil_scoped_acquire acq; - object retval(src(std::forward<Args>(args)...)); + object retval(func(std::forward<Args>(args)...)); /* Visual studio 2015 parser issue: need parentheses around this expression */ return (retval.template cast<Return>()); }; @@ -78,4 +82,4 @@ public: }; NAMESPACE_END(detail) -NAMESPACE_END(pybind11) +NAMESPACE_END(PYBIND11_NAMESPACE) diff --git a/ext/pybind11/include/pybind11/iostream.h b/ext/pybind11/include/pybind11/iostream.h new file mode 100644 index 000000000..a9c27aac1 --- /dev/null +++ b/ext/pybind11/include/pybind11/iostream.h @@ -0,0 +1,200 @@ +/* + pybind11/iostream.h -- Tools to assist with redirecting cout and cerr to Python + + Copyright (c) 2017 Henry F. Schreiner + + All rights reserved. Use of this source code is governed by a + BSD-style license that can be found in the LICENSE file. +*/ + +#pragma once + +#include "pybind11.h" + +#include <streambuf> +#include <ostream> +#include <string> +#include <memory> +#include <iostream> + +NAMESPACE_BEGIN(PYBIND11_NAMESPACE) +NAMESPACE_BEGIN(detail) + +// Buffer that writes to Python instead of C++ +class pythonbuf : public std::streambuf { +private: + using traits_type = std::streambuf::traits_type; + + char d_buffer[1024]; + object pywrite; + object pyflush; + + int overflow(int c) { + if (!traits_type::eq_int_type(c, traits_type::eof())) { + *pptr() = traits_type::to_char_type(c); + pbump(1); + } + return sync() ? traits_type::not_eof(c) : traits_type::eof(); + } + + int sync() { + if (pbase() != pptr()) { + // This subtraction cannot be negative, so dropping the sign + str line(pbase(), static_cast<size_t>(pptr() - pbase())); + + pywrite(line); + pyflush(); + + setp(pbase(), epptr()); + } + return 0; + } + +public: + pythonbuf(object pyostream) + : pywrite(pyostream.attr("write")), + pyflush(pyostream.attr("flush")) { + setp(d_buffer, d_buffer + sizeof(d_buffer) - 1); + } + + /// Sync before destroy + ~pythonbuf() { + sync(); + } +}; + +NAMESPACE_END(detail) + + +/** \rst + This a move-only guard that redirects output. + + .. code-block:: cpp + + #include <pybind11/iostream.h> + + ... + + { + py::scoped_ostream_redirect output; + std::cout << "Hello, World!"; // Python stdout + } // <-- return std::cout to normal + + You can explicitly pass the c++ stream and the python object, + for example to guard stderr instead. + + .. code-block:: cpp + + { + py::scoped_ostream_redirect output{std::cerr, py::module::import("sys").attr("stderr")}; + std::cerr << "Hello, World!"; + } + \endrst */ +class scoped_ostream_redirect { +protected: + std::streambuf *old; + std::ostream &costream; + detail::pythonbuf buffer; + +public: + scoped_ostream_redirect( + std::ostream &costream = std::cout, + object pyostream = module::import("sys").attr("stdout")) + : costream(costream), buffer(pyostream) { + old = costream.rdbuf(&buffer); + } + + ~scoped_ostream_redirect() { + costream.rdbuf(old); + } + + scoped_ostream_redirect(const scoped_ostream_redirect &) = delete; + scoped_ostream_redirect(scoped_ostream_redirect &&other) = default; + scoped_ostream_redirect &operator=(const scoped_ostream_redirect &) = delete; + scoped_ostream_redirect &operator=(scoped_ostream_redirect &&) = delete; +}; + + +/** \rst + Like `scoped_ostream_redirect`, but redirects cerr by default. This class + is provided primary to make ``py::call_guard`` easier to make. + + .. code-block:: cpp + + m.def("noisy_func", &noisy_func, + py::call_guard<scoped_ostream_redirect, + scoped_estream_redirect>()); + +\endrst */ +class scoped_estream_redirect : public scoped_ostream_redirect { +public: + scoped_estream_redirect( + std::ostream &costream = std::cerr, + object pyostream = module::import("sys").attr("stderr")) + : scoped_ostream_redirect(costream,pyostream) {} +}; + + +NAMESPACE_BEGIN(detail) + +// Class to redirect output as a context manager. C++ backend. +class OstreamRedirect { + bool do_stdout_; + bool do_stderr_; + std::unique_ptr<scoped_ostream_redirect> redirect_stdout; + std::unique_ptr<scoped_estream_redirect> redirect_stderr; + +public: + OstreamRedirect(bool do_stdout = true, bool do_stderr = true) + : do_stdout_(do_stdout), do_stderr_(do_stderr) {} + + void enter() { + if (do_stdout_) + redirect_stdout.reset(new scoped_ostream_redirect()); + if (do_stderr_) + redirect_stderr.reset(new scoped_estream_redirect()); + } + + void exit() { + redirect_stdout.reset(); + redirect_stderr.reset(); + } +}; + +NAMESPACE_END(detail) + +/** \rst + This is a helper function to add a C++ redirect context manager to Python + instead of using a C++ guard. To use it, add the following to your binding code: + + .. code-block:: cpp + + #include <pybind11/iostream.h> + + ... + + py::add_ostream_redirect(m, "ostream_redirect"); + + You now have a Python context manager that redirects your output: + + .. code-block:: python + + with m.ostream_redirect(): + m.print_to_cout_function() + + This manager can optionally be told which streams to operate on: + + .. code-block:: python + + with m.ostream_redirect(stdout=true, stderr=true): + m.noisy_function_with_error_printing() + + \endrst */ +inline class_<detail::OstreamRedirect> add_ostream_redirect(module m, std::string name = "ostream_redirect") { + return class_<detail::OstreamRedirect>(m, name.c_str(), module_local()) + .def(init<bool,bool>(), arg("stdout")=true, arg("stderr")=true) + .def("__enter__", &detail::OstreamRedirect::enter) + .def("__exit__", [](detail::OstreamRedirect &self, args) { self.exit(); }); +} + +NAMESPACE_END(PYBIND11_NAMESPACE) diff --git a/ext/pybind11/include/pybind11/numpy.h b/ext/pybind11/include/pybind11/numpy.h index 3227a12eb..55bb81698 100644 --- a/ext/pybind11/include/pybind11/numpy.h +++ b/ext/pybind11/include/pybind11/numpy.h @@ -29,12 +29,12 @@ #endif /* This will be true on all flat address space platforms and allows us to reduce the - whole npy_intp / size_t / Py_intptr_t business down to just size_t for all size + whole npy_intp / ssize_t / Py_intptr_t business down to just ssize_t for all size and dimension types (e.g. shape, strides, indexing), instead of inflicting this upon the library user. */ -static_assert(sizeof(size_t) == sizeof(Py_intptr_t), "size_t != Py_intptr_t"); +static_assert(sizeof(ssize_t) == sizeof(Py_intptr_t), "ssize_t != Py_intptr_t"); -NAMESPACE_BEGIN(pybind11) +NAMESPACE_BEGIN(PYBIND11_NAMESPACE) class array; // Forward declaration @@ -129,6 +129,11 @@ struct npy_api { NPY_STRING_, NPY_UNICODE_, NPY_VOID_ }; + typedef struct { + Py_intptr_t *ptr; + int len; + } PyArray_Dims; + static npy_api& get() { static npy_api api = lookup(); return api; @@ -141,11 +146,13 @@ struct npy_api { return (bool) PyObject_TypeCheck(obj, PyArrayDescr_Type_); } + unsigned int (*PyArray_GetNDArrayCFeatureVersion_)(); PyObject *(*PyArray_DescrFromType_)(int); PyObject *(*PyArray_NewFromDescr_) (PyTypeObject *, PyObject *, int, Py_intptr_t *, Py_intptr_t *, void *, int, PyObject *); PyObject *(*PyArray_DescrNewFromType_)(int); + int (*PyArray_CopyInto_)(PyObject *, PyObject *); PyObject *(*PyArray_NewCopy_)(PyObject *, int); PyTypeObject *PyArray_Type_; PyTypeObject *PyVoidArrType_Type_; @@ -158,14 +165,18 @@ struct npy_api { Py_ssize_t *, PyObject **, PyObject *); PyObject *(*PyArray_Squeeze_)(PyObject *); int (*PyArray_SetBaseObject_)(PyObject *, PyObject *); + PyObject* (*PyArray_Resize_)(PyObject*, PyArray_Dims*, int, int); private: enum functions { + API_PyArray_GetNDArrayCFeatureVersion = 211, API_PyArray_Type = 2, API_PyArrayDescr_Type = 3, API_PyVoidArrType_Type = 39, API_PyArray_DescrFromType = 45, API_PyArray_DescrFromScalar = 57, API_PyArray_FromAny = 69, + API_PyArray_Resize = 80, + API_PyArray_CopyInto = 82, API_PyArray_NewCopy = 85, API_PyArray_NewFromDescr = 94, API_PyArray_DescrNewFromType = 9, @@ -186,12 +197,17 @@ private: #endif npy_api api; #define DECL_NPY_API(Func) api.Func##_ = (decltype(api.Func##_)) api_ptr[API_##Func]; + DECL_NPY_API(PyArray_GetNDArrayCFeatureVersion); + if (api.PyArray_GetNDArrayCFeatureVersion_() < 0x7) + pybind11_fail("pybind11 numpy support requires numpy >= 1.7.0"); DECL_NPY_API(PyArray_Type); DECL_NPY_API(PyVoidArrType_Type); DECL_NPY_API(PyArrayDescr_Type); DECL_NPY_API(PyArray_DescrFromType); DECL_NPY_API(PyArray_DescrFromScalar); DECL_NPY_API(PyArray_FromAny); + DECL_NPY_API(PyArray_Resize); + DECL_NPY_API(PyArray_CopyInto); DECL_NPY_API(PyArray_NewCopy); DECL_NPY_API(PyArray_NewFromDescr); DECL_NPY_API(PyArray_DescrNewFromType); @@ -230,18 +246,68 @@ template <typename T, size_t N> struct is_std_array<std::array<T, N>> : std::tru template <typename T> struct is_complex : std::false_type { }; template <typename T> struct is_complex<std::complex<T>> : std::true_type { }; +template <typename T> struct array_info_scalar { + typedef T type; + static constexpr bool is_array = false; + static constexpr bool is_empty = false; + static PYBIND11_DESCR extents() { return _(""); } + static void append_extents(list& /* shape */) { } +}; +// Computes underlying type and a comma-separated list of extents for array +// types (any mix of std::array and built-in arrays). An array of char is +// treated as scalar because it gets special handling. +template <typename T> struct array_info : array_info_scalar<T> { }; +template <typename T, size_t N> struct array_info<std::array<T, N>> { + using type = typename array_info<T>::type; + static constexpr bool is_array = true; + static constexpr bool is_empty = (N == 0) || array_info<T>::is_empty; + static constexpr size_t extent = N; + + // appends the extents to shape + static void append_extents(list& shape) { + shape.append(N); + array_info<T>::append_extents(shape); + } + + template<typename T2 = T, enable_if_t<!array_info<T2>::is_array, int> = 0> + static PYBIND11_DESCR extents() { + return _<N>(); + } + + template<typename T2 = T, enable_if_t<array_info<T2>::is_array, int> = 0> + static PYBIND11_DESCR extents() { + return concat(_<N>(), array_info<T>::extents()); + } +}; +// For numpy we have special handling for arrays of characters, so we don't include +// the size in the array extents. +template <size_t N> struct array_info<char[N]> : array_info_scalar<char[N]> { }; +template <size_t N> struct array_info<std::array<char, N>> : array_info_scalar<std::array<char, N>> { }; +template <typename T, size_t N> struct array_info<T[N]> : array_info<std::array<T, N>> { }; +template <typename T> using remove_all_extents_t = typename array_info<T>::type; + template <typename T> using is_pod_struct = all_of< - std::is_pod<T>, // since we're accessing directly in memory we need a POD type + std::is_standard_layout<T>, // since we're accessing directly in memory we need a standard layout type +#if !defined(__GNUG__) || defined(_LIBCPP_VERSION) || defined(_GLIBCXX_USE_CXX11_ABI) + // _GLIBCXX_USE_CXX11_ABI indicates that we're using libstdc++ from GCC 5 or newer, independent + // of the actual compiler (Clang can also use libstdc++, but it always defines __GNUC__ == 4). + std::is_trivially_copyable<T>, +#else + // GCC 4 doesn't implement is_trivially_copyable, so approximate it + std::is_trivially_destructible<T>, + satisfies_any_of<T, std::has_trivial_copy_constructor, std::has_trivial_copy_assign>, +#endif satisfies_none_of<T, std::is_reference, std::is_array, is_std_array, std::is_arithmetic, is_complex, std::is_enum> >; -template <size_t Dim = 0, typename Strides> size_t byte_offset_unsafe(const Strides &) { return 0; } -template <size_t Dim = 0, typename Strides, typename... Ix> -size_t byte_offset_unsafe(const Strides &strides, size_t i, Ix... index) { +template <ssize_t Dim = 0, typename Strides> ssize_t byte_offset_unsafe(const Strides &) { return 0; } +template <ssize_t Dim = 0, typename Strides, typename... Ix> +ssize_t byte_offset_unsafe(const Strides &strides, ssize_t i, Ix... index) { return i * strides[Dim] + byte_offset_unsafe<Dim + 1>(strides, index...); } -/** Proxy class providing unsafe, unchecked const access to array data. This is constructed through +/** + * Proxy class providing unsafe, unchecked const access to array data. This is constructed through * the `unchecked<T, N>()` method of `array` or the `unchecked<N>()` method of `array_t<T>`. `Dims` * will be -1 for dimensions determined at runtime. */ @@ -252,66 +318,68 @@ protected: const unsigned char *data_; // Storing the shape & strides in local variables (i.e. these arrays) allows the compiler to // make large performance gains on big, nested loops, but requires compile-time dimensions - conditional_t<Dynamic, const size_t *, std::array<size_t, (size_t) Dims>> - shape_, strides_; - const size_t dims_; + conditional_t<Dynamic, const ssize_t *, std::array<ssize_t, (size_t) Dims>> + shape_, strides_; + const ssize_t dims_; friend class pybind11::array; // Constructor for compile-time dimensions: template <bool Dyn = Dynamic> - unchecked_reference(const void *data, const size_t *shape, const size_t *strides, enable_if_t<!Dyn, size_t>) + unchecked_reference(const void *data, const ssize_t *shape, const ssize_t *strides, enable_if_t<!Dyn, ssize_t>) : data_{reinterpret_cast<const unsigned char *>(data)}, dims_{Dims} { - for (size_t i = 0; i < dims_; i++) { + for (size_t i = 0; i < (size_t) dims_; i++) { shape_[i] = shape[i]; strides_[i] = strides[i]; } } // Constructor for runtime dimensions: template <bool Dyn = Dynamic> - unchecked_reference(const void *data, const size_t *shape, const size_t *strides, enable_if_t<Dyn, size_t> dims) + unchecked_reference(const void *data, const ssize_t *shape, const ssize_t *strides, enable_if_t<Dyn, ssize_t> dims) : data_{reinterpret_cast<const unsigned char *>(data)}, shape_{shape}, strides_{strides}, dims_{dims} {} public: - /** Unchecked const reference access to data at the given indices. For a compile-time known + /** + * Unchecked const reference access to data at the given indices. For a compile-time known * number of dimensions, this requires the correct number of arguments; for run-time * dimensionality, this is not checked (and so is up to the caller to use safely). */ template <typename... Ix> const T &operator()(Ix... index) const { - static_assert(sizeof...(Ix) == Dims || Dynamic, + static_assert(ssize_t{sizeof...(Ix)} == Dims || Dynamic, "Invalid number of indices for unchecked array reference"); - return *reinterpret_cast<const T *>(data_ + byte_offset_unsafe(strides_, size_t(index)...)); + return *reinterpret_cast<const T *>(data_ + byte_offset_unsafe(strides_, ssize_t(index)...)); } - /** Unchecked const reference access to data; this operator only participates if the reference + /** + * Unchecked const reference access to data; this operator only participates if the reference * is to a 1-dimensional array. When present, this is exactly equivalent to `obj(index)`. */ - template <size_t D = Dims, typename = enable_if_t<D == 1 || Dynamic>> - const T &operator[](size_t index) const { return operator()(index); } + template <ssize_t D = Dims, typename = enable_if_t<D == 1 || Dynamic>> + const T &operator[](ssize_t index) const { return operator()(index); } /// Pointer access to the data at the given indices. - template <typename... Ix> const T *data(Ix... ix) const { return &operator()(size_t(ix)...); } + template <typename... Ix> const T *data(Ix... ix) const { return &operator()(ssize_t(ix)...); } /// Returns the item size, i.e. sizeof(T) - constexpr static size_t itemsize() { return sizeof(T); } + constexpr static ssize_t itemsize() { return sizeof(T); } /// Returns the shape (i.e. size) of dimension `dim` - size_t shape(size_t dim) const { return shape_[dim]; } + ssize_t shape(ssize_t dim) const { return shape_[(size_t) dim]; } /// Returns the number of dimensions of the array - size_t ndim() const { return dims_; } + ssize_t ndim() const { return dims_; } /// Returns the total number of elements in the referenced array, i.e. the product of the shapes template <bool Dyn = Dynamic> - enable_if_t<!Dyn, size_t> size() const { - return std::accumulate(shape_.begin(), shape_.end(), (size_t) 1, std::multiplies<size_t>()); + enable_if_t<!Dyn, ssize_t> size() const { + return std::accumulate(shape_.begin(), shape_.end(), (ssize_t) 1, std::multiplies<ssize_t>()); } template <bool Dyn = Dynamic> - enable_if_t<Dyn, size_t> size() const { - return std::accumulate(shape_, shape_ + ndim(), (size_t) 1, std::multiplies<size_t>()); + enable_if_t<Dyn, ssize_t> size() const { + return std::accumulate(shape_, shape_ + ndim(), (ssize_t) 1, std::multiplies<ssize_t>()); } /// Returns the total number of bytes used by the referenced data. Note that the actual span in /// memory may be larger if the referenced array has non-contiguous strides (e.g. for a slice). - size_t nbytes() const { + ssize_t nbytes() const { return size() * itemsize(); } }; @@ -325,26 +393,27 @@ class unchecked_mutable_reference : public unchecked_reference<T, Dims> { public: /// Mutable, unchecked access to data at the given indices. template <typename... Ix> T& operator()(Ix... index) { - static_assert(sizeof...(Ix) == Dims || Dynamic, + static_assert(ssize_t{sizeof...(Ix)} == Dims || Dynamic, "Invalid number of indices for unchecked array reference"); return const_cast<T &>(ConstBase::operator()(index...)); } - /** Mutable, unchecked access data at the given index; this operator only participates if the + /** + * Mutable, unchecked access data at the given index; this operator only participates if the * reference is to a 1-dimensional array (or has runtime dimensions). When present, this is * exactly equivalent to `obj(index)`. */ - template <size_t D = Dims, typename = enable_if_t<D == 1 || Dynamic>> - T &operator[](size_t index) { return operator()(index); } + template <ssize_t D = Dims, typename = enable_if_t<D == 1 || Dynamic>> + T &operator[](ssize_t index) { return operator()(index); } /// Mutable pointer access to the data at the given indices. - template <typename... Ix> T *mutable_data(Ix... ix) { return &operator()(size_t(ix)...); } + template <typename... Ix> T *mutable_data(Ix... ix) { return &operator()(ssize_t(ix)...); } }; -template <typename T, size_t Dim> +template <typename T, ssize_t Dim> struct type_caster<unchecked_reference<T, Dim>> { static_assert(Dim == 0 && Dim > 0 /* always fail */, "unchecked array proxy object is not castable"); }; -template <typename T, size_t Dim> +template <typename T, ssize_t Dim> struct type_caster<unchecked_mutable_reference<T, Dim>> : type_caster<unchecked_reference<T, Dim>> {}; NAMESPACE_END(detail) @@ -365,7 +434,7 @@ public: dtype(const char *format) : dtype(std::string(format)) { } - dtype(list names, list formats, list offsets, size_t itemsize) { + dtype(list names, list formats, list offsets, ssize_t itemsize) { dict args; args["names"] = names; args["formats"] = formats; @@ -388,8 +457,8 @@ public: } /// Size of the data type in bytes. - size_t itemsize() const { - return (size_t) detail::array_descriptor_proxy(m_ptr)->elsize; + ssize_t itemsize() const { + return detail::array_descriptor_proxy(m_ptr)->elsize; } /// Returns true for structured data types. @@ -409,7 +478,7 @@ private: return reinterpret_borrow<object>(obj); } - dtype strip_padding(size_t itemsize) { + dtype strip_padding(ssize_t itemsize) { // Recursively strip all void fields with empty names that are generated for // padding fields (as of NumPy v1.11). if (!has_fields()) @@ -453,14 +522,20 @@ public: forcecast = detail::npy_api::NPY_ARRAY_FORCECAST_ }; - array() : array(0, static_cast<const double *>(nullptr)) {} + array() : array({{0}}, static_cast<const double *>(nullptr)) {} - array(const pybind11::dtype &dt, const std::vector<size_t> &shape, - const std::vector<size_t> &strides, const void *ptr = nullptr, - handle base = handle()) { - auto& api = detail::npy_api::get(); - auto ndim = shape.size(); - if (shape.size() != strides.size()) + using ShapeContainer = detail::any_container<ssize_t>; + using StridesContainer = detail::any_container<ssize_t>; + + // Constructs an array taking shape/strides from arbitrary container types + array(const pybind11::dtype &dt, ShapeContainer shape, StridesContainer strides, + const void *ptr = nullptr, handle base = handle()) { + + if (strides->empty()) + *strides = c_strides(*shape, dt.itemsize()); + + auto ndim = shape->size(); + if (ndim != strides->size()) pybind11_fail("NumPy: shape ndim doesn't match strides ndim"); auto descr = dt; @@ -474,13 +549,12 @@ public: flags = detail::npy_api::NPY_ARRAY_WRITEABLE_; } + auto &api = detail::npy_api::get(); auto tmp = reinterpret_steal<object>(api.PyArray_NewFromDescr_( - api.PyArray_Type_, descr.release().ptr(), (int) ndim, - reinterpret_cast<Py_intptr_t *>(const_cast<size_t*>(shape.data())), - reinterpret_cast<Py_intptr_t *>(const_cast<size_t*>(strides.data())), + api.PyArray_Type_, descr.release().ptr(), (int) ndim, shape->data(), strides->data(), const_cast<void *>(ptr), flags, nullptr)); if (!tmp) - pybind11_fail("NumPy: unable to create array!"); + throw error_already_set(); if (ptr) { if (base) { api.PyArray_SetBaseObject_(tmp.ptr(), base.inc_ref().ptr()); @@ -491,27 +565,23 @@ public: m_ptr = tmp.release().ptr(); } - array(const pybind11::dtype &dt, const std::vector<size_t> &shape, - const void *ptr = nullptr, handle base = handle()) - : array(dt, shape, default_strides(shape, dt.itemsize()), ptr, base) { } + array(const pybind11::dtype &dt, ShapeContainer shape, const void *ptr = nullptr, handle base = handle()) + : array(dt, std::move(shape), {}, ptr, base) { } - array(const pybind11::dtype &dt, size_t count, const void *ptr = nullptr, - handle base = handle()) - : array(dt, std::vector<size_t>{ count }, ptr, base) { } + template <typename T, typename = detail::enable_if_t<std::is_integral<T>::value && !std::is_same<bool, T>::value>> + array(const pybind11::dtype &dt, T count, const void *ptr = nullptr, handle base = handle()) + : array(dt, {{count}}, ptr, base) { } - template<typename T> array(const std::vector<size_t>& shape, - const std::vector<size_t>& strides, - const T* ptr, handle base = handle()) - : array(pybind11::dtype::of<T>(), shape, strides, (const void *) ptr, base) { } + template <typename T> + array(ShapeContainer shape, StridesContainer strides, const T *ptr, handle base = handle()) + : array(pybind11::dtype::of<T>(), std::move(shape), std::move(strides), ptr, base) { } template <typename T> - array(const std::vector<size_t> &shape, const T *ptr, - handle base = handle()) - : array(shape, default_strides(shape, sizeof(T)), ptr, base) { } + array(ShapeContainer shape, const T *ptr, handle base = handle()) + : array(std::move(shape), {}, ptr, base) { } template <typename T> - array(size_t count, const T *ptr, handle base = handle()) - : array(std::vector<size_t>{ count }, ptr, base) { } + explicit array(ssize_t count, const T *ptr, handle base = handle()) : array({count}, {}, ptr, base) { } explicit array(const buffer_info &info) : array(pybind11::dtype(info), info.shape, info.strides, info.ptr) { } @@ -522,23 +592,23 @@ public: } /// Total number of elements - size_t size() const { - return std::accumulate(shape(), shape() + ndim(), (size_t) 1, std::multiplies<size_t>()); + ssize_t size() const { + return std::accumulate(shape(), shape() + ndim(), (ssize_t) 1, std::multiplies<ssize_t>()); } /// Byte size of a single element - size_t itemsize() const { - return (size_t) detail::array_descriptor_proxy(detail::array_proxy(m_ptr)->descr)->elsize; + ssize_t itemsize() const { + return detail::array_descriptor_proxy(detail::array_proxy(m_ptr)->descr)->elsize; } /// Total number of bytes - size_t nbytes() const { + ssize_t nbytes() const { return size() * itemsize(); } /// Number of dimensions - size_t ndim() const { - return (size_t) detail::array_proxy(m_ptr)->nd; + ssize_t ndim() const { + return detail::array_proxy(m_ptr)->nd; } /// Base object @@ -547,24 +617,24 @@ public: } /// Dimensions of the array - const size_t* shape() const { - return reinterpret_cast<const size_t *>(detail::array_proxy(m_ptr)->dimensions); + const ssize_t* shape() const { + return detail::array_proxy(m_ptr)->dimensions; } /// Dimension along a given axis - size_t shape(size_t dim) const { + ssize_t shape(ssize_t dim) const { if (dim >= ndim()) fail_dim_check(dim, "invalid axis"); return shape()[dim]; } /// Strides of the array - const size_t* strides() const { - return reinterpret_cast<const size_t *>(detail::array_proxy(m_ptr)->strides); + const ssize_t* strides() const { + return detail::array_proxy(m_ptr)->strides; } /// Stride along a given axis - size_t strides(size_t dim) const { + ssize_t strides(ssize_t dim) const { if (dim >= ndim()) fail_dim_check(dim, "invalid axis"); return strides()[dim]; @@ -601,40 +671,42 @@ public: /// Byte offset from beginning of the array to a given index (full or partial). /// May throw if the index would lead to out of bounds access. - template<typename... Ix> size_t offset_at(Ix... index) const { - if (sizeof...(index) > ndim()) + template<typename... Ix> ssize_t offset_at(Ix... index) const { + if ((ssize_t) sizeof...(index) > ndim()) fail_dim_check(sizeof...(index), "too many indices for an array"); - return byte_offset(size_t(index)...); + return byte_offset(ssize_t(index)...); } - size_t offset_at() const { return 0; } + ssize_t offset_at() const { return 0; } /// Item count from beginning of the array to a given index (full or partial). /// May throw if the index would lead to out of bounds access. - template<typename... Ix> size_t index_at(Ix... index) const { + template<typename... Ix> ssize_t index_at(Ix... index) const { return offset_at(index...) / itemsize(); } - /** Returns a proxy object that provides access to the array's data without bounds or + /** + * Returns a proxy object that provides access to the array's data without bounds or * dimensionality checking. Will throw if the array is missing the `writeable` flag. Use with * care: the array must not be destroyed or reshaped for the duration of the returned object, * and the caller must take care not to access invalid dimensions or dimension indices. */ - template <typename T, ssize_t Dims = -1> detail::unchecked_mutable_reference<T, Dims> mutable_unchecked() { - if (Dims >= 0 && ndim() != (size_t) Dims) + template <typename T, ssize_t Dims = -1> detail::unchecked_mutable_reference<T, Dims> mutable_unchecked() & { + if (Dims >= 0 && ndim() != Dims) throw std::domain_error("array has incorrect number of dimensions: " + std::to_string(ndim()) + "; expected " + std::to_string(Dims)); return detail::unchecked_mutable_reference<T, Dims>(mutable_data(), shape(), strides(), ndim()); } - /** Returns a proxy object that provides const access to the array's data without bounds or + /** + * Returns a proxy object that provides const access to the array's data without bounds or * dimensionality checking. Unlike `mutable_unchecked()`, this does not require that the * underlying array have the `writable` flag. Use with care: the array must not be destroyed or * reshaped for the duration of the returned object, and the caller must take care not to access * invalid dimensions or dimension indices. */ - template <typename T, ssize_t Dims = -1> detail::unchecked_reference<T, Dims> unchecked() const { - if (Dims >= 0 && ndim() != (size_t) Dims) + template <typename T, ssize_t Dims = -1> detail::unchecked_reference<T, Dims> unchecked() const & { + if (Dims >= 0 && ndim() != Dims) throw std::domain_error("array has incorrect number of dimensions: " + std::to_string(ndim()) + "; expected " + std::to_string(Dims)); return detail::unchecked_reference<T, Dims>(data(), shape(), strides(), ndim()); @@ -646,6 +718,21 @@ public: return reinterpret_steal<array>(api.PyArray_Squeeze_(m_ptr)); } + /// Resize array to given shape + /// If refcheck is true and more that one reference exist to this array + /// then resize will succeed only if it makes a reshape, i.e. original size doesn't change + void resize(ShapeContainer new_shape, bool refcheck = true) { + detail::npy_api::PyArray_Dims d = { + new_shape->data(), int(new_shape->size()) + }; + // try to resize, set ordering param to -1 cause it's not used anyway + object new_array = reinterpret_steal<object>( + detail::npy_api::get().PyArray_Resize_(m_ptr, &d, int(refcheck), -1) + ); + if (!new_array) throw error_already_set(); + if (isinstance<array>(new_array)) { *this = std::move(new_array); } + } + /// Ensure that the argument is a NumPy array /// In case of an error, nullptr is returned and the Python error is cleared. static array ensure(handle h, int ExtraFlags = 0) { @@ -658,14 +745,14 @@ public: protected: template<typename, typename> friend struct detail::npy_format_descriptor; - void fail_dim_check(size_t dim, const std::string& msg) const { + void fail_dim_check(ssize_t dim, const std::string& msg) const { throw index_error(msg + ": " + std::to_string(dim) + " (ndim = " + std::to_string(ndim()) + ")"); } - template<typename... Ix> size_t byte_offset(Ix... index) const { + template<typename... Ix> ssize_t byte_offset(Ix... index) const { check_dimensions(index...); - return detail::byte_offset_unsafe(strides(), size_t(index)...); + return detail::byte_offset_unsafe(strides(), ssize_t(index)...); } void check_writeable() const { @@ -673,25 +760,31 @@ protected: throw std::domain_error("array is not writeable"); } - static std::vector<size_t> default_strides(const std::vector<size_t>& shape, size_t itemsize) { + // Default, C-style strides + static std::vector<ssize_t> c_strides(const std::vector<ssize_t> &shape, ssize_t itemsize) { auto ndim = shape.size(); - std::vector<size_t> strides(ndim); - if (ndim) { - std::fill(strides.begin(), strides.end(), itemsize); - for (size_t i = 0; i < ndim - 1; i++) - for (size_t j = 0; j < ndim - 1 - i; j++) - strides[j] *= shape[ndim - 1 - i]; - } + std::vector<ssize_t> strides(ndim, itemsize); + for (size_t i = ndim - 1; i > 0; --i) + strides[i - 1] = strides[i] * shape[i]; + return strides; + } + + // F-style strides; default when constructing an array_t with `ExtraFlags & f_style` + static std::vector<ssize_t> f_strides(const std::vector<ssize_t> &shape, ssize_t itemsize) { + auto ndim = shape.size(); + std::vector<ssize_t> strides(ndim, itemsize); + for (size_t i = 1; i < ndim; ++i) + strides[i] = strides[i - 1] * shape[i - 1]; return strides; } template<typename... Ix> void check_dimensions(Ix... index) const { - check_dimensions_impl(size_t(0), shape(), size_t(index)...); + check_dimensions_impl(ssize_t(0), shape(), ssize_t(index)...); } - void check_dimensions_impl(size_t, const size_t*) const { } + void check_dimensions_impl(ssize_t, const ssize_t*) const { } - template<typename... Ix> void check_dimensions_impl(size_t axis, const size_t* shape, size_t i, Ix... index) const { + template<typename... Ix> void check_dimensions_impl(ssize_t axis, const ssize_t* shape, ssize_t i, Ix... index) const { if (i >= *shape) { throw index_error(std::string("index ") + std::to_string(i) + " is out of bounds for axis " + std::to_string(axis) + @@ -702,50 +795,58 @@ protected: /// Create array from any object -- always returns a new reference static PyObject *raw_array(PyObject *ptr, int ExtraFlags = 0) { - if (ptr == nullptr) + if (ptr == nullptr) { + PyErr_SetString(PyExc_ValueError, "cannot create a pybind11::array from a nullptr"); return nullptr; + } return detail::npy_api::get().PyArray_FromAny_( ptr, nullptr, 0, 0, detail::npy_api::NPY_ARRAY_ENSUREARRAY_ | ExtraFlags, nullptr); } }; template <typename T, int ExtraFlags = array::forcecast> class array_t : public array { +private: + struct private_ctor {}; + // Delegating constructor needed when both moving and accessing in the same constructor + array_t(private_ctor, ShapeContainer &&shape, StridesContainer &&strides, const T *ptr, handle base) + : array(std::move(shape), std::move(strides), ptr, base) {} public: + static_assert(!detail::array_info<T>::is_array, "Array types cannot be used with array_t"); + using value_type = T; array_t() : array(0, static_cast<const T *>(nullptr)) {} - array_t(handle h, borrowed_t) : array(h, borrowed) { } - array_t(handle h, stolen_t) : array(h, stolen) { } + array_t(handle h, borrowed_t) : array(h, borrowed_t{}) { } + array_t(handle h, stolen_t) : array(h, stolen_t{}) { } PYBIND11_DEPRECATED("Use array_t<T>::ensure() instead") - array_t(handle h, bool is_borrowed) : array(raw_array_t(h.ptr()), stolen) { + array_t(handle h, bool is_borrowed) : array(raw_array_t(h.ptr()), stolen_t{}) { if (!m_ptr) PyErr_Clear(); if (!is_borrowed) Py_XDECREF(h.ptr()); } - array_t(const object &o) : array(raw_array_t(o.ptr()), stolen) { + array_t(const object &o) : array(raw_array_t(o.ptr()), stolen_t{}) { if (!m_ptr) throw error_already_set(); } explicit array_t(const buffer_info& info) : array(info) { } - array_t(const std::vector<size_t> &shape, - const std::vector<size_t> &strides, const T *ptr = nullptr, - handle base = handle()) - : array(shape, strides, ptr, base) { } + array_t(ShapeContainer shape, StridesContainer strides, const T *ptr = nullptr, handle base = handle()) + : array(std::move(shape), std::move(strides), ptr, base) { } - explicit array_t(const std::vector<size_t> &shape, const T *ptr = nullptr, - handle base = handle()) - : array(shape, ptr, base) { } + explicit array_t(ShapeContainer shape, const T *ptr = nullptr, handle base = handle()) + : array_t(private_ctor{}, std::move(shape), + ExtraFlags & f_style ? f_strides(*shape, itemsize()) : c_strides(*shape, itemsize()), + ptr, base) { } explicit array_t(size_t count, const T *ptr = nullptr, handle base = handle()) - : array(count, ptr, base) { } + : array({count}, {}, ptr, base) { } - constexpr size_t itemsize() const { + constexpr ssize_t itemsize() const { return sizeof(T); } - template<typename... Ix> size_t index_at(Ix... index) const { + template<typename... Ix> ssize_t index_at(Ix... index) const { return offset_at(index...) / itemsize(); } @@ -761,32 +862,34 @@ public: template<typename... Ix> const T& at(Ix... index) const { if (sizeof...(index) != ndim()) fail_dim_check(sizeof...(index), "index dimension mismatch"); - return *(static_cast<const T*>(array::data()) + byte_offset(size_t(index)...) / itemsize()); + return *(static_cast<const T*>(array::data()) + byte_offset(ssize_t(index)...) / itemsize()); } // Mutable reference to element at a given index template<typename... Ix> T& mutable_at(Ix... index) { if (sizeof...(index) != ndim()) fail_dim_check(sizeof...(index), "index dimension mismatch"); - return *(static_cast<T*>(array::mutable_data()) + byte_offset(size_t(index)...) / itemsize()); + return *(static_cast<T*>(array::mutable_data()) + byte_offset(ssize_t(index)...) / itemsize()); } - /** Returns a proxy object that provides access to the array's data without bounds or + /** + * Returns a proxy object that provides access to the array's data without bounds or * dimensionality checking. Will throw if the array is missing the `writeable` flag. Use with * care: the array must not be destroyed or reshaped for the duration of the returned object, * and the caller must take care not to access invalid dimensions or dimension indices. */ - template <ssize_t Dims = -1> detail::unchecked_mutable_reference<T, Dims> mutable_unchecked() { + template <ssize_t Dims = -1> detail::unchecked_mutable_reference<T, Dims> mutable_unchecked() & { return array::mutable_unchecked<T, Dims>(); } - /** Returns a proxy object that provides const access to the array's data without bounds or + /** + * Returns a proxy object that provides const access to the array's data without bounds or * dimensionality checking. Unlike `unchecked()`, this does not require that the underlying * array have the `writable` flag. Use with care: the array must not be destroyed or reshaped * for the duration of the returned object, and the caller must take care not to access invalid * dimensions or dimension indices. */ - template <ssize_t Dims = -1> detail::unchecked_reference<T, Dims> unchecked() const { + template <ssize_t Dims = -1> detail::unchecked_reference<T, Dims> unchecked() const & { return array::unchecked<T, Dims>(); } @@ -808,8 +911,10 @@ public: protected: /// Create array from any object -- always returns a new reference static PyObject *raw_array_t(PyObject *ptr) { - if (ptr == nullptr) + if (ptr == nullptr) { + PyErr_SetString(PyExc_ValueError, "cannot create a pybind11::array_t from a nullptr"); return nullptr; + } return detail::npy_api::get().PyArray_FromAny_( ptr, dtype::of<T>().release().ptr(), 0, 0, detail::npy_api::NPY_ARRAY_ENSUREARRAY_ | ExtraFlags, nullptr); @@ -838,6 +943,15 @@ struct format_descriptor<T, detail::enable_if_t<std::is_enum<T>::value>> { } }; +template <typename T> +struct format_descriptor<T, detail::enable_if_t<detail::array_info<T>::is_array>> { + static std::string format() { + using detail::_; + PYBIND11_DESCR extents = _("(") + detail::array_info<T>::extents() + _(")"); + return extents.text() + format_descriptor<detail::remove_all_extents_t<T>>::format(); + } +}; + NAMESPACE_BEGIN(detail) template <typename T, int ExtraFlags> struct pyobject_caster<array_t<T, ExtraFlags>> { @@ -906,6 +1020,20 @@ template <size_t N> struct npy_format_descriptor<char[N]> { PYBIND11_DECL_CHAR_F template <size_t N> struct npy_format_descriptor<std::array<char, N>> { PYBIND11_DECL_CHAR_FMT }; #undef PYBIND11_DECL_CHAR_FMT +template<typename T> struct npy_format_descriptor<T, enable_if_t<array_info<T>::is_array>> { +private: + using base_descr = npy_format_descriptor<typename array_info<T>::type>; +public: + static_assert(!array_info<T>::is_empty, "Zero-sized arrays are not supported"); + + static PYBIND11_DESCR name() { return _("(") + array_info<T>::extents() + _(")") + base_descr::name(); } + static pybind11::dtype dtype() { + list shape; + array_info<T>::append_extents(shape); + return pybind11::dtype::from_args(pybind11::make_tuple(base_descr::dtype(), shape)); + } +}; + template<typename T> struct npy_format_descriptor<T, enable_if_t<std::is_enum<T>::value>> { private: using base_descr = npy_format_descriptor<typename std::underlying_type<T>::type>; @@ -916,16 +1044,15 @@ public: struct field_descriptor { const char *name; - size_t offset; - size_t size; - size_t alignment; + ssize_t offset; + ssize_t size; std::string format; dtype descr; }; inline PYBIND11_NOINLINE void register_structured_dtype( const std::initializer_list<field_descriptor>& fields, - const std::type_info& tinfo, size_t itemsize, + const std::type_info& tinfo, ssize_t itemsize, bool (*direct_converter)(PyObject *, void *&)) { auto& numpy_internals = get_numpy_internals(); @@ -953,15 +1080,17 @@ inline PYBIND11_NOINLINE void register_structured_dtype( std::vector<field_descriptor> ordered_fields(fields); std::sort(ordered_fields.begin(), ordered_fields.end(), [](const field_descriptor &a, const field_descriptor &b) { return a.offset < b.offset; }); - size_t offset = 0; + ssize_t offset = 0; std::ostringstream oss; - oss << "T{"; + // mark the structure as unaligned with '^', because numpy and C++ don't + // always agree about alignment (particularly for complex), and we're + // explicitly listing all our padding. This depends on none of the fields + // overriding the endianness. Putting the ^ in front of individual fields + // isn't guaranteed to work due to https://github.com/numpy/numpy/issues/9049 + oss << "^T{"; for (auto& field : ordered_fields) { if (field.offset > offset) oss << (field.offset - offset) << 'x'; - // mark unaligned fields with '^' (unaligned native type) - if (field.offset % field.alignment) - oss << '^'; oss << field.format << ':' << field.name << ':'; offset = field.offset + field.size; } @@ -1020,10 +1149,14 @@ private: } }; +#ifdef __CLION_IDE__ // replace heavy macro with dummy code for the IDE (doesn't affect code) +# define PYBIND11_NUMPY_DTYPE(Type, ...) ((void)0) +# define PYBIND11_NUMPY_DTYPE_EX(Type, ...) ((void)0) +#else + #define PYBIND11_FIELD_DESCRIPTOR_EX(T, Field, Name) \ ::pybind11::detail::field_descriptor { \ Name, offsetof(T, Field), sizeof(decltype(std::declval<T>().Field)), \ - alignof(decltype(std::declval<T>().Field)), \ ::pybind11::format_descriptor<decltype(std::declval<T>().Field)>::format(), \ ::pybind11::detail::npy_format_descriptor<decltype(std::declval<T>().Field)>::dtype() \ } @@ -1088,6 +1221,8 @@ private: ::pybind11::detail::npy_format_descriptor<Type>::register_dtype \ ({PYBIND11_MAP2_LIST (PYBIND11_FIELD_DESCRIPTOR_EX, Type, __VA_ARGS__)}) +#endif // __CLION_IDE__ + template <class T> using array_iterator = typename std::add_pointer<T>::type; @@ -1103,13 +1238,13 @@ array_iterator<T> array_end(const buffer_info& buffer) { class common_iterator { public: - using container_type = std::vector<size_t>; + using container_type = std::vector<ssize_t>; using value_type = container_type::value_type; using size_type = container_type::size_type; common_iterator() : p_ptr(0), m_strides() {} - common_iterator(void* ptr, const container_type& strides, const std::vector<size_t>& shape) + common_iterator(void* ptr, const container_type& strides, const container_type& shape) : p_ptr(reinterpret_cast<char*>(ptr)), m_strides(strides.size()) { m_strides.back() = static_cast<value_type>(strides.back()); for (size_type i = m_strides.size() - 1; i != 0; --i) { @@ -1134,16 +1269,16 @@ private: template <size_t N> class multi_array_iterator { public: - using container_type = std::vector<size_t>; + using container_type = std::vector<ssize_t>; multi_array_iterator(const std::array<buffer_info, N> &buffers, - const std::vector<size_t> &shape) + const container_type &shape) : m_shape(shape.size()), m_index(shape.size(), 0), m_common_iterator() { // Manual copy to avoid conversion warning if using std::copy for (size_t i = 0; i < shape.size(); ++i) - m_shape[i] = static_cast<container_type::value_type>(shape[i]); + m_shape[i] = shape[i]; container_type strides(shape.size()); for (size_t i = 0; i < N; ++i) @@ -1163,8 +1298,8 @@ public: return *this; } - template <size_t K, class T> const T& data() const { - return *reinterpret_cast<T*>(m_common_iterator[K].data()); + template <size_t K, class T = void> T* data() const { + return reinterpret_cast<T*>(m_common_iterator[K].data()); } private: @@ -1172,8 +1307,9 @@ private: using common_iter = common_iterator; void init_common_iterator(const buffer_info &buffer, - const std::vector<size_t> &shape, - common_iter &iterator, container_type &strides) { + const container_type &shape, + common_iter &iterator, + container_type &strides) { auto buffer_shape_iter = buffer.shape.rbegin(); auto buffer_strides_iter = buffer.strides.rbegin(); auto shape_iter = shape.rbegin(); @@ -1181,7 +1317,7 @@ private: while (buffer_shape_iter != buffer.shape.rend()) { if (*shape_iter == *buffer_shape_iter) - *strides_iter = static_cast<size_t>(*buffer_strides_iter); + *strides_iter = *buffer_strides_iter; else *strides_iter = 0; @@ -1212,13 +1348,13 @@ enum class broadcast_trivial { non_trivial, c_trivial, f_trivial }; // singleton or a full-size, C-contiguous (`c_trivial`) or Fortran-contiguous (`f_trivial`) storage // buffer; returns `non_trivial` otherwise. template <size_t N> -broadcast_trivial broadcast(const std::array<buffer_info, N> &buffers, size_t &ndim, std::vector<size_t> &shape) { - ndim = std::accumulate(buffers.begin(), buffers.end(), size_t(0), [](size_t res, const buffer_info& buf) { +broadcast_trivial broadcast(const std::array<buffer_info, N> &buffers, ssize_t &ndim, std::vector<ssize_t> &shape) { + ndim = std::accumulate(buffers.begin(), buffers.end(), ssize_t(0), [](ssize_t res, const buffer_info &buf) { return std::max(res, buf.ndim); }); shape.clear(); - shape.resize(ndim, 1); + shape.resize((size_t) ndim, 1); // Figure out the output size, and make sure all input arrays conform (i.e. are either size 1 or // the full size). @@ -1253,7 +1389,7 @@ broadcast_trivial broadcast(const std::array<buffer_info, N> &buffers, size_t &n // Check for C contiguity (but only if previous inputs were also C contiguous) if (trivial_broadcast_c) { - size_t expect_stride = buffers[i].itemsize; + ssize_t expect_stride = buffers[i].itemsize; auto end = buffers[i].shape.crend(); for (auto shape_iter = buffers[i].shape.crbegin(), stride_iter = buffers[i].strides.crbegin(); trivial_broadcast_c && shape_iter != end; ++shape_iter, ++stride_iter) { @@ -1266,7 +1402,7 @@ broadcast_trivial broadcast(const std::array<buffer_info, N> &buffers, size_t &n // Check for Fortran contiguity (if previous inputs were also F contiguous) if (trivial_broadcast_f) { - size_t expect_stride = buffers[i].itemsize; + ssize_t expect_stride = buffers[i].itemsize; auto end = buffers[i].shape.cend(); for (auto shape_iter = buffers[i].shape.cbegin(), stride_iter = buffers[i].strides.cbegin(); trivial_broadcast_f && shape_iter != end; ++shape_iter, ++stride_iter) { @@ -1284,82 +1420,143 @@ broadcast_trivial broadcast(const std::array<buffer_info, N> &buffers, size_t &n broadcast_trivial::non_trivial; } +template <typename T> +struct vectorize_arg { + static_assert(!std::is_rvalue_reference<T>::value, "Functions with rvalue reference arguments cannot be vectorized"); + // The wrapped function gets called with this type: + using call_type = remove_reference_t<T>; + // Is this a vectorized argument? + static constexpr bool vectorize = + satisfies_any_of<call_type, std::is_arithmetic, is_complex, std::is_pod>::value && + satisfies_none_of<call_type, std::is_pointer, std::is_array, is_std_array, std::is_enum>::value && + (!std::is_reference<T>::value || + (std::is_lvalue_reference<T>::value && std::is_const<call_type>::value)); + // Accept this type: an array for vectorized types, otherwise the type as-is: + using type = conditional_t<vectorize, array_t<remove_cv_t<call_type>, array::forcecast>, T>; +}; + template <typename Func, typename Return, typename... Args> struct vectorize_helper { - typename std::remove_reference<Func>::type f; +private: static constexpr size_t N = sizeof...(Args); + static constexpr size_t NVectorized = constexpr_sum(vectorize_arg<Args>::vectorize...); + static_assert(NVectorized >= 1, + "pybind11::vectorize(...) requires a function with at least one vectorizable argument"); +public: template <typename T> - explicit vectorize_helper(T&&f) : f(std::forward<T>(f)) { } + explicit vectorize_helper(T &&f) : f(std::forward<T>(f)) { } - object operator()(array_t<Args, array::forcecast>... args) { - return run(args..., make_index_sequence<N>()); + object operator()(typename vectorize_arg<Args>::type... args) { + return run(args..., + make_index_sequence<N>(), + select_indices<vectorize_arg<Args>::vectorize...>(), + make_index_sequence<NVectorized>()); } - template <size_t ... Index> object run(array_t<Args, array::forcecast>&... args, index_sequence<Index...> index) { - /* Request buffers from all parameters */ - std::array<buffer_info, N> buffers {{ args.request()... }}; +private: + remove_reference_t<Func> f; + + template <size_t Index> using param_n_t = typename pack_element<Index, typename vectorize_arg<Args>::call_type...>::type; + + // Runs a vectorized function given arguments tuple and three index sequences: + // - Index is the full set of 0 ... (N-1) argument indices; + // - VIndex is the subset of argument indices with vectorized parameters, letting us access + // vectorized arguments (anything not in this sequence is passed through) + // - BIndex is a incremental sequence (beginning at 0) of the same size as VIndex, so that + // we can store vectorized buffer_infos in an array (argument VIndex has its buffer at + // index BIndex in the array). + template <size_t... Index, size_t... VIndex, size_t... BIndex> object run( + typename vectorize_arg<Args>::type &...args, + index_sequence<Index...> i_seq, index_sequence<VIndex...> vi_seq, index_sequence<BIndex...> bi_seq) { + + // Pointers to values the function was called with; the vectorized ones set here will start + // out as array_t<T> pointers, but they will be changed them to T pointers before we make + // call the wrapped function. Non-vectorized pointers are left as-is. + std::array<void *, N> params{{ &args... }}; + + // The array of `buffer_info`s of vectorized arguments: + std::array<buffer_info, NVectorized> buffers{{ reinterpret_cast<array *>(params[VIndex])->request()... }}; /* Determine dimensions parameters of output array */ - size_t ndim = 0; - std::vector<size_t> shape(0); - auto trivial = broadcast(buffers, ndim, shape); - - size_t size = 1; - std::vector<size_t> strides(ndim); - if (ndim > 0) { - if (trivial == broadcast_trivial::f_trivial) { - strides[0] = sizeof(Return); - for (size_t i = 1; i < ndim; ++i) { - strides[i] = strides[i - 1] * shape[i - 1]; - size *= shape[i - 1]; - } - size *= shape[ndim - 1]; - } - else { - strides[ndim-1] = sizeof(Return); - for (size_t i = ndim - 1; i > 0; --i) { - strides[i - 1] = strides[i] * shape[i]; - size *= shape[i]; - } - size *= shape[0]; - } + ssize_t nd = 0; + std::vector<ssize_t> shape(0); + auto trivial = broadcast(buffers, nd, shape); + size_t ndim = (size_t) nd; + + size_t size = std::accumulate(shape.begin(), shape.end(), (size_t) 1, std::multiplies<size_t>()); + + // If all arguments are 0-dimension arrays (i.e. single values) return a plain value (i.e. + // not wrapped in an array). + if (size == 1 && ndim == 0) { + PYBIND11_EXPAND_SIDE_EFFECTS(params[VIndex] = buffers[BIndex].ptr); + return cast(f(*reinterpret_cast<param_n_t<Index> *>(params[Index])...)); } - if (size == 1) - return cast(f(*reinterpret_cast<Args *>(buffers[Index].ptr)...)); + array_t<Return> result; + if (trivial == broadcast_trivial::f_trivial) result = array_t<Return, array::f_style>(shape); + else result = array_t<Return>(shape); - array_t<Return> result(shape, strides); - auto buf = result.request(); - auto output = (Return *) buf.ptr; + if (size == 0) return result; /* Call the function */ - if (trivial == broadcast_trivial::non_trivial) { - apply_broadcast<Index...>(buffers, buf, index); - } else { - for (size_t i = 0; i < size; ++i) - output[i] = f((reinterpret_cast<Args *>(buffers[Index].ptr)[buffers[Index].size == 1 ? 0 : i])...); - } + if (trivial == broadcast_trivial::non_trivial) + apply_broadcast(buffers, params, result, i_seq, vi_seq, bi_seq); + else + apply_trivial(buffers, params, result.mutable_data(), size, i_seq, vi_seq, bi_seq); return result; } - template <size_t... Index> - void apply_broadcast(const std::array<buffer_info, N> &buffers, - buffer_info &output, index_sequence<Index...>) { - using input_iterator = multi_array_iterator<N>; - using output_iterator = array_iterator<Return>; + template <size_t... Index, size_t... VIndex, size_t... BIndex> + void apply_trivial(std::array<buffer_info, NVectorized> &buffers, + std::array<void *, N> ¶ms, + Return *out, + size_t size, + index_sequence<Index...>, index_sequence<VIndex...>, index_sequence<BIndex...>) { + + // Initialize an array of mutable byte references and sizes with references set to the + // appropriate pointer in `params`; as we iterate, we'll increment each pointer by its size + // (except for singletons, which get an increment of 0). + std::array<std::pair<unsigned char *&, const size_t>, NVectorized> vecparams{{ + std::pair<unsigned char *&, const size_t>( + reinterpret_cast<unsigned char *&>(params[VIndex] = buffers[BIndex].ptr), + buffers[BIndex].size == 1 ? 0 : sizeof(param_n_t<VIndex>) + )... + }}; + + for (size_t i = 0; i < size; ++i) { + out[i] = f(*reinterpret_cast<param_n_t<Index> *>(params[Index])...); + for (auto &x : vecparams) x.first += x.second; + } + } - input_iterator input_iter(buffers, output.shape); - output_iterator output_end = array_end<Return>(output); + template <size_t... Index, size_t... VIndex, size_t... BIndex> + void apply_broadcast(std::array<buffer_info, NVectorized> &buffers, + std::array<void *, N> ¶ms, + array_t<Return> &output_array, + index_sequence<Index...>, index_sequence<VIndex...>, index_sequence<BIndex...>) { - for (output_iterator iter = array_begin<Return>(output); - iter != output_end; ++iter, ++input_iter) { - *iter = f((input_iter.template data<Index, Args>())...); + buffer_info output = output_array.request(); + multi_array_iterator<NVectorized> input_iter(buffers, output.shape); + + for (array_iterator<Return> iter = array_begin<Return>(output), end = array_end<Return>(output); + iter != end; + ++iter, ++input_iter) { + PYBIND11_EXPAND_SIDE_EFFECTS(( + params[VIndex] = input_iter.template data<BIndex>() + )); + *iter = f(*reinterpret_cast<param_n_t<Index> *>(std::get<Index>(params))...); } } }; +template <typename Func, typename Return, typename... Args> +vectorize_helper<Func, Return, Args...> +vectorize_extractor(const Func &f, Return (*) (Args ...)) { + return detail::vectorize_helper<Func, Return, Args...>(f); +} + template <typename T, int Flags> struct handle_type_name<array_t<T, Flags>> { static PYBIND11_DESCR name() { return _("numpy.ndarray[") + npy_format_descriptor<T>::name() + _("]"); @@ -1368,25 +1565,35 @@ template <typename T, int Flags> struct handle_type_name<array_t<T, Flags>> { NAMESPACE_END(detail) -template <typename Func, typename Return, typename... Args> -detail::vectorize_helper<Func, Return, Args...> -vectorize(const Func &f, Return (*) (Args ...)) { - return detail::vectorize_helper<Func, Return, Args...>(f); -} - +// Vanilla pointer vectorizer: template <typename Return, typename... Args> -detail::vectorize_helper<Return (*) (Args ...), Return, Args...> +detail::vectorize_helper<Return (*)(Args...), Return, Args...> vectorize(Return (*f) (Args ...)) { - return vectorize<Return (*) (Args ...), Return, Args...>(f, f); + return detail::vectorize_helper<Return (*)(Args...), Return, Args...>(f); } -template <typename Func, typename FuncType = typename detail::remove_class<decltype(&std::remove_reference<Func>::type::operator())>::type> +// lambda vectorizer: +template <typename Func, detail::enable_if_t<detail::is_lambda<Func>::value, int> = 0> auto vectorize(Func &&f) -> decltype( - vectorize(std::forward<Func>(f), (FuncType *) nullptr)) { - return vectorize(std::forward<Func>(f), (FuncType *) nullptr); + detail::vectorize_extractor(std::forward<Func>(f), (detail::function_signature_t<Func> *) nullptr)) { + return detail::vectorize_extractor(std::forward<Func>(f), (detail::function_signature_t<Func> *) nullptr); +} + +// Vectorize a class method (non-const): +template <typename Return, typename Class, typename... Args, + typename Helper = detail::vectorize_helper<decltype(std::mem_fn(std::declval<Return (Class::*)(Args...)>())), Return, Class *, Args...>> +Helper vectorize(Return (Class::*f)(Args...)) { + return Helper(std::mem_fn(f)); +} + +// Vectorize a class method (non-const): +template <typename Return, typename Class, typename... Args, + typename Helper = detail::vectorize_helper<decltype(std::mem_fn(std::declval<Return (Class::*)(Args...) const>())), Return, const Class *, Args...>> +Helper vectorize(Return (Class::*f)(Args...) const) { + return Helper(std::mem_fn(f)); } -NAMESPACE_END(pybind11) +NAMESPACE_END(PYBIND11_NAMESPACE) #if defined(_MSC_VER) #pragma warning(pop) diff --git a/ext/pybind11/include/pybind11/operators.h b/ext/pybind11/include/pybind11/operators.h index 2e78c01a3..b3dd62c3b 100644 --- a/ext/pybind11/include/pybind11/operators.h +++ b/ext/pybind11/include/pybind11/operators.h @@ -13,9 +13,12 @@ #if defined(__clang__) && !defined(__INTEL_COMPILER) # pragma clang diagnostic ignored "-Wunsequenced" // multiple unsequenced modifications to 'self' (when using def(py::self OP Type())) +#elif defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable: 4127) // warning C4127: Conditional expression is constant #endif -NAMESPACE_BEGIN(pybind11) +NAMESPACE_BEGIN(PYBIND11_NAMESPACE) NAMESPACE_BEGIN(detail) /// Enumeration with all supported operator types @@ -25,7 +28,7 @@ enum op_id : int { op_int, op_long, op_float, op_str, op_cmp, op_gt, op_ge, op_lt, op_le, op_eq, op_ne, op_iadd, op_isub, op_imul, op_idiv, op_imod, op_ilshift, op_irshift, op_iand, op_ixor, op_ior, op_complex, op_bool, op_nonzero, - op_repr, op_truediv + op_repr, op_truediv, op_itruediv, op_hash }; enum op_type : int { @@ -49,22 +52,32 @@ template <op_id, op_type, typename B, typename L, typename R> struct op_impl { } /// Operator implementation generator template <op_id id, op_type ot, typename L, typename R> struct op_ { template <typename Class, typename... Extra> void execute(Class &cl, const Extra&... extra) const { - typedef typename Class::type Base; - typedef typename std::conditional<std::is_same<L, self_t>::value, Base, L>::type L_type; - typedef typename std::conditional<std::is_same<R, self_t>::value, Base, R>::type R_type; - typedef op_impl<id, ot, Base, L_type, R_type> op; + using Base = typename Class::type; + using L_type = conditional_t<std::is_same<L, self_t>::value, Base, L>; + using R_type = conditional_t<std::is_same<R, self_t>::value, Base, R>; + using op = op_impl<id, ot, Base, L_type, R_type>; cl.def(op::name(), &op::execute, is_operator(), extra...); + #if PY_MAJOR_VERSION < 3 + if (id == op_truediv || id == op_itruediv) + cl.def(id == op_itruediv ? "__idiv__" : ot == op_l ? "__div__" : "__rdiv__", + &op::execute, is_operator(), extra...); + #endif } template <typename Class, typename... Extra> void execute_cast(Class &cl, const Extra&... extra) const { - typedef typename Class::type Base; - typedef typename std::conditional<std::is_same<L, self_t>::value, Base, L>::type L_type; - typedef typename std::conditional<std::is_same<R, self_t>::value, Base, R>::type R_type; - typedef op_impl<id, ot, Base, L_type, R_type> op; + using Base = typename Class::type; + using L_type = conditional_t<std::is_same<L, self_t>::value, Base, L>; + using R_type = conditional_t<std::is_same<R, self_t>::value, Base, R>; + using op = op_impl<id, ot, Base, L_type, R_type>; cl.def(op::name(), &op::execute_cast, is_operator(), extra...); + #if PY_MAJOR_VERSION < 3 + if (id == op_truediv || id == op_itruediv) + cl.def(id == op_itruediv ? "__idiv__" : ot == op_l ? "__div__" : "__rdiv__", + &op::execute, is_operator(), extra...); + #endif } }; -#define PYBIND11_BINARY_OPERATOR(id, rid, op, expr) \ +#define PYBIND11_BINARY_OPERATOR(id, rid, op, expr) \ template <typename B, typename L, typename R> struct op_impl<op_##id, op_l, B, L, R> { \ static char const* name() { return "__" #id "__"; } \ static auto execute(const L &l, const R &r) -> decltype(expr) { return (expr); } \ @@ -85,7 +98,7 @@ template <typename T> op_<op_##id, op_r, T, self_t> op(const T &, const self_t & return op_<op_##id, op_r, T, self_t>(); \ } -#define PYBIND11_INPLACE_OPERATOR(id, op, expr) \ +#define PYBIND11_INPLACE_OPERATOR(id, op, expr) \ template <typename B, typename L, typename R> struct op_impl<op_##id, op_l, B, L, R> { \ static char const* name() { return "__" #id "__"; } \ static auto execute(L &l, const R &r) -> decltype(expr) { return expr; } \ @@ -95,7 +108,7 @@ template <typename T> op_<op_##id, op_l, self_t, T> op(const self_t &, const T & return op_<op_##id, op_l, self_t, T>(); \ } -#define PYBIND11_UNARY_OPERATOR(id, op, expr) \ +#define PYBIND11_UNARY_OPERATOR(id, op, expr) \ template <typename B, typename L> struct op_impl<op_##id, op_u, B, L, undefined_t> { \ static char const* name() { return "__" #id "__"; } \ static auto execute(const L &l) -> decltype(expr) { return expr; } \ @@ -108,11 +121,7 @@ inline op_<op_##id, op_u, self_t, undefined_t> op(const self_t &) { PYBIND11_BINARY_OPERATOR(sub, rsub, operator-, l - r) PYBIND11_BINARY_OPERATOR(add, radd, operator+, l + r) PYBIND11_BINARY_OPERATOR(mul, rmul, operator*, l * r) -#if PY_MAJOR_VERSION >= 3 PYBIND11_BINARY_OPERATOR(truediv, rtruediv, operator/, l / r) -#else -PYBIND11_BINARY_OPERATOR(div, rdiv, operator/, l / r) -#endif PYBIND11_BINARY_OPERATOR(mod, rmod, operator%, l % r) PYBIND11_BINARY_OPERATOR(lshift, rlshift, operator<<, l << r) PYBIND11_BINARY_OPERATOR(rshift, rrshift, operator>>, l >> r) @@ -129,7 +138,7 @@ PYBIND11_BINARY_OPERATOR(le, ge, operator<=, l <= r) PYBIND11_INPLACE_OPERATOR(iadd, operator+=, l += r) PYBIND11_INPLACE_OPERATOR(isub, operator-=, l -= r) PYBIND11_INPLACE_OPERATOR(imul, operator*=, l *= r) -PYBIND11_INPLACE_OPERATOR(idiv, operator/=, l /= r) +PYBIND11_INPLACE_OPERATOR(itruediv, operator/=, l /= r) PYBIND11_INPLACE_OPERATOR(imod, operator%=, l %= r) PYBIND11_INPLACE_OPERATOR(ilshift, operator<<=, l <<= r) PYBIND11_INPLACE_OPERATOR(irshift, operator>>=, l >>= r) @@ -139,6 +148,7 @@ PYBIND11_INPLACE_OPERATOR(ior, operator|=, l |= r) PYBIND11_UNARY_OPERATOR(neg, operator-, -l) PYBIND11_UNARY_OPERATOR(pos, operator+, +l) PYBIND11_UNARY_OPERATOR(abs, abs, std::abs(l)) +PYBIND11_UNARY_OPERATOR(hash, hash, std::hash<L>()(l)) PYBIND11_UNARY_OPERATOR(invert, operator~, (~l)) PYBIND11_UNARY_OPERATOR(bool, operator!, !!l) PYBIND11_UNARY_OPERATOR(int, int_, (int) l) @@ -151,4 +161,8 @@ NAMESPACE_END(detail) using detail::self; -NAMESPACE_END(pybind11) +NAMESPACE_END(PYBIND11_NAMESPACE) + +#if defined(_MSC_VER) +# pragma warning(pop) +#endif diff --git a/ext/pybind11/include/pybind11/options.h b/ext/pybind11/include/pybind11/options.h index 3105551dd..cc1e1f6f0 100644 --- a/ext/pybind11/include/pybind11/options.h +++ b/ext/pybind11/include/pybind11/options.h @@ -9,9 +9,9 @@ #pragma once -#include "common.h" +#include "detail/common.h" -NAMESPACE_BEGIN(pybind11) +NAMESPACE_BEGIN(PYBIND11_NAMESPACE) class options { public: @@ -62,4 +62,4 @@ private: state previous_state; }; -NAMESPACE_END(pybind11) +NAMESPACE_END(PYBIND11_NAMESPACE) diff --git a/ext/pybind11/include/pybind11/pybind11.h b/ext/pybind11/include/pybind11/pybind11.h index 5976a36d8..613135a7a 100644 --- a/ext/pybind11/include/pybind11/pybind11.h +++ b/ext/pybind11/include/pybind11/pybind11.h @@ -21,8 +21,12 @@ # pragma warning(disable: 4522) // warning C4522: multiple assignment operators specified #elif defined(__INTEL_COMPILER) # pragma warning(push) +# pragma warning(disable: 68) // integer conversion resulted in a change of sign # pragma warning(disable: 186) // pointless comparison of unsigned integer with zero +# pragma warning(disable: 878) // incompatible exception specifications # pragma warning(disable: 1334) // the "template" keyword used for syntactic disambiguation may only be used within a template +# pragma warning(disable: 1682) // implicit conversion of a 64-bit integral type to a smaller integral type (potential portability problem) +# pragma warning(disable: 1875) // offsetof applied to non-POD (Plain Old Data) types is nonstandard # pragma warning(disable: 2196) // warning #2196: routine is both "inline" and "noinline" #elif defined(__GNUG__) && !defined(__clang__) # pragma GCC diagnostic push @@ -31,13 +35,17 @@ # pragma GCC diagnostic ignored "-Wmissing-field-initializers" # pragma GCC diagnostic ignored "-Wstrict-aliasing" # pragma GCC diagnostic ignored "-Wattributes" +# if __GNUC__ >= 7 +# pragma GCC diagnostic ignored "-Wnoexcept-type" +# endif #endif #include "attr.h" #include "options.h" -#include "class_support.h" +#include "detail/class.h" +#include "detail/init.h" -NAMESPACE_BEGIN(pybind11) +NAMESPACE_BEGIN(PYBIND11_NAMESPACE) /// Wraps an arbitrary C++ function/method/lambda function/.. into a callable Python object class cpp_function : public function { @@ -51,16 +59,11 @@ public: } /// Construct a cpp_function from a lambda function (possibly with internal state) - template <typename Func, typename... Extra, typename = detail::enable_if_t< - detail::satisfies_none_of< - typename std::remove_reference<Func>::type, - std::is_function, std::is_pointer, std::is_member_pointer - >::value> - > + template <typename Func, typename... Extra, + typename = detail::enable_if_t<detail::is_lambda<Func>::value>> cpp_function(Func &&f, const Extra&... extra) { - using FuncType = typename detail::remove_class<decltype(&std::remove_reference<Func>::type::operator())>::type; initialize(std::forward<Func>(f), - (FuncType *) nullptr, extra...); + (detail::function_signature_t<Func> *) nullptr, extra...); } /// Construct a cpp_function from a class method (non-const) @@ -90,7 +93,7 @@ protected: template <typename Func, typename Return, typename... Args, typename... Extra> void initialize(Func &&f, Return (*)(Args...), const Extra&... extra) { - struct capture { typename std::remove_reference<Func>::type f; }; + struct capture { detail::remove_reference_t<Func> f; }; /* Store the function including any extra state it might have (e.g. a lambda capture object) */ auto rec = make_function_record(); @@ -143,9 +146,12 @@ protected: /* Override policy for rvalues -- usually to enforce rvp::move on an rvalue */ const auto policy = detail::return_value_policy_override<Return>::policy(call.func.policy); + /* Function scope guard -- defaults to the compile-to-nothing `void_type` */ + using Guard = detail::extract_guard_t<Extra...>; + /* Perform the function call */ - handle result = cast_out::cast(args_converter.template call<Return>(cap->f), - policy, call.parent); + handle result = cast_out::cast( + std::move(args_converter).template call<Return, Guard>(cap->f), policy, call.parent); /* Invoke call policy post-call hook */ detail::process_attributes<Extra...>::postcall(call, result); @@ -193,6 +199,22 @@ protected: a.descr = strdup(a.value.attr("__repr__")().cast<std::string>().c_str()); } + rec->is_constructor = !strcmp(rec->name, "__init__") || !strcmp(rec->name, "__setstate__"); + +#if !defined(NDEBUG) && !defined(PYBIND11_DISABLE_NEW_STYLE_INIT_WARNING) + if (rec->is_constructor && !rec->is_new_style_constructor) { + const auto class_name = std::string(((PyTypeObject *) rec->scope.ptr())->tp_name); + const auto func_name = std::string(rec->name); + PyErr_WarnEx( + PyExc_FutureWarning, + ("pybind11-bound class '" + class_name + "' is using an old-style " + "placement-new '" + func_name + "' which has been deprecated. See " + "the upgrade guide in pybind11's docs. This message is only visible " + "when compiled in debug mode.").c_str(), 0 + ); + } +#endif + /* Generate a proper function signature */ std::string signature; size_t type_depth = 0, char_index = 0, type_index = 0, arg_index = 0; @@ -234,6 +256,13 @@ protected: .cast<std::string>() + "."; #endif signature += tinfo->type->tp_name; + } else if (rec->is_new_style_constructor && arg_index == 0) { + // A new-style `__init__` takes `self` as `value_and_holder`. + // Rewrite it to the proper class type. +#if defined(PYPY_VERSION) + signature += rec->scope.attr("__module__").cast<std::string>() + "."; +#endif + signature += ((PyTypeObject *) rec->scope.ptr())->tp_name; } else { std::string tname(t->name()); detail::clean_type_id(tname); @@ -246,7 +275,7 @@ protected: if (type_depth != 0 || types[type_index] != nullptr) pybind11_fail("Internal error while parsing type signature (2)"); - #if !defined(PYBIND11_CPP14) + #if !defined(PYBIND11_CONSTEXPR_DESCR) delete[] types; delete[] text; #endif @@ -262,13 +291,10 @@ protected: #endif rec->signature = strdup(signature.c_str()); rec->args.shrink_to_fit(); - rec->is_constructor = !strcmp(rec->name, "__init__") || !strcmp(rec->name, "__setstate__"); rec->nargs = (std::uint16_t) args; -#if PY_MAJOR_VERSION < 3 - if (rec->sibling && PyMethod_Check(rec->sibling.ptr())) - rec->sibling = PyMethod_GET_FUNCTION(rec->sibling.ptr()); -#endif + if (rec->sibling && PYBIND11_INSTANCE_METHOD_CHECK(rec->sibling.ptr())) + rec->sibling = PYBIND11_INSTANCE_METHOD_GET_FUNCTION(rec->sibling.ptr()); detail::function_record *chain = nullptr, *chain_start = rec; if (rec->sibling) { @@ -277,7 +303,7 @@ protected: chain = (detail::function_record *) rec_capsule; /* Never append a method to an overload chain of a parent class; instead, hide the parent's overloads in this case */ - if (chain->scope != rec->scope) + if (!chain->scope.is(rec->scope)) chain = nullptr; } // Don't trigger for things like the default __init__, which are wrapper_descriptors that we are intentionally replacing @@ -289,7 +315,7 @@ protected: if (!chain) { /* No existing overload was found, create a new function object */ rec->def = new PyMethodDef(); - memset(rec->def, 0, sizeof(PyMethodDef)); + std::memset(rec->def, 0, sizeof(PyMethodDef)); rec->def->ml_name = rec->name; rec->def->ml_meth = reinterpret_cast<PyCFunction>(*dispatcher); rec->def->ml_flags = METH_VARARGS | METH_KEYWORDS; @@ -315,6 +341,15 @@ protected: m_ptr = rec->sibling.ptr(); inc_ref(); chain_start = chain; + if (chain->is_method != rec->is_method) + pybind11_fail("overloading a method with both static and instance methods is not supported; " + #if defined(NDEBUG) + "compile in debug mode for more details" + #else + "error while attempting to bind " + std::string(rec->is_method ? "instance" : "static") + " method " + + std::string(pybind11::str(rec->scope.attr("__name__"))) + "." + std::string(rec->name) + signature + #endif + ); while (chain->next) chain = chain->next; chain->next = rec; @@ -405,6 +440,23 @@ protected: handle parent = n_args_in > 0 ? PyTuple_GET_ITEM(args_in, 0) : nullptr, result = PYBIND11_TRY_NEXT_OVERLOAD; + auto self_value_and_holder = value_and_holder(); + if (overloads->is_constructor) { + const auto tinfo = get_type_info((PyTypeObject *) overloads->scope.ptr()); + const auto pi = reinterpret_cast<instance *>(parent.ptr()); + self_value_and_holder = pi->get_value_and_holder(tinfo, false); + + if (!self_value_and_holder.type || !self_value_and_holder.inst) { + PyErr_SetString(PyExc_TypeError, "__init__(self, ...) called with invalid `self` argument"); + return nullptr; + } + + // If this value is already registered it must mean __init__ is invoked multiple times; + // we really can't support that in C++, so just ignore the second __init__. + if (self_value_and_holder.instance_registered()) + return none().release().ptr(); + } + try { // We do this in two passes: in the first pass, we load arguments with `convert=false`; // in the second, we allow conversion (except for arguments with an explicit @@ -452,19 +504,37 @@ protected: size_t args_to_copy = std::min(pos_args, n_args_in); size_t args_copied = 0; + // 0. Inject new-style `self` argument + if (func.is_new_style_constructor) { + // The `value` may have been preallocated by an old-style `__init__` + // if it was a preceding candidate for overload resolution. + if (self_value_and_holder) + self_value_and_holder.type->dealloc(self_value_and_holder); + + call.init_self = PyTuple_GET_ITEM(args_in, 0); + call.args.push_back(reinterpret_cast<PyObject *>(&self_value_and_holder)); + call.args_convert.push_back(false); + ++args_copied; + } + // 1. Copy any position arguments given. - bool bad_kwarg = false; + bool bad_arg = false; for (; args_copied < args_to_copy; ++args_copied) { - if (kwargs_in && args_copied < func.args.size() && func.args[args_copied].name - && PyDict_GetItemString(kwargs_in, func.args[args_copied].name)) { - bad_kwarg = true; + argument_record *arg_rec = args_copied < func.args.size() ? &func.args[args_copied] : nullptr; + if (kwargs_in && arg_rec && arg_rec->name && PyDict_GetItemString(kwargs_in, arg_rec->name)) { + bad_arg = true; break; } - call.args.push_back(PyTuple_GET_ITEM(args_in, args_copied)); - call.args_convert.push_back(args_copied < func.args.size() ? func.args[args_copied].convert : true); + handle arg(PyTuple_GET_ITEM(args_in, args_copied)); + if (arg_rec && !arg_rec->none && arg.is_none()) { + bad_arg = true; + break; + } + call.args.push_back(arg); + call.args_convert.push_back(arg_rec ? arg_rec->convert : true); } - if (bad_kwarg) + if (bad_arg) continue; // Maybe it was meant for another overload (issue #688) // We'll need to copy this if we steal some kwargs for defaults @@ -555,6 +625,7 @@ protected: // 6. Call the function. try { + loader_life_support guard{}; result = func.impl(call); } catch (reference_cast_error &) { result = PYBIND11_TRY_NEXT_OVERLOAD; @@ -583,6 +654,7 @@ protected: // The no-conversion pass finished without success, try again with conversion allowed for (auto &call : second_pass) { try { + loader_life_support guard{}; result = call.func.impl(call); } catch (reference_cast_error &) { result = PYBIND11_TRY_NEXT_OVERLOAD; @@ -622,6 +694,16 @@ protected: return nullptr; } + auto append_note_if_missing_header_is_suspected = [](std::string &msg) { + if (msg.find("std::") != std::string::npos) { + msg += "\n\n" + "Did you forget to `#include <pybind11/stl.h>`? Or <pybind11/complex.h>,\n" + "<pybind11/functional.h>, <pybind11/chrono.h>, etc. Some automatic\n" + "conversions are optional and require extra headers to be included\n" + "when compiling your pybind11 module."; + } + }; + if (result.ptr() == PYBIND11_TRY_NEXT_OVERLOAD) { if (overloads->is_operator) return handle(Py_NotImplemented).inc_ref().ptr(); @@ -679,20 +761,20 @@ protected: } } + append_note_if_missing_header_is_suspected(msg); PyErr_SetString(PyExc_TypeError, msg.c_str()); return nullptr; } else if (!result) { std::string msg = "Unable to convert function return value to a " "Python type! The signature was\n\t"; msg += it->signature; + append_note_if_missing_header_is_suspected(msg); PyErr_SetString(PyExc_TypeError, msg.c_str()); return nullptr; } else { - if (overloads->is_constructor) { - /* When a constructor ran successfully, the corresponding - holder type (e.g. std::unique_ptr) must still be initialized. */ - auto tinfo = get_type_info(Py_TYPE(parent.ptr())); - tinfo->init_holder(parent.ptr(), nullptr); + if (overloads->is_constructor && !self_value_and_holder.holder_constructed()) { + auto *pi = reinterpret_cast<instance *>(parent.ptr()); + self_value_and_holder.type->init_instance(pi, nullptr); } return result.ptr(); } @@ -709,7 +791,7 @@ public: if (!options::show_user_defined_docstrings()) doc = nullptr; #if PY_MAJOR_VERSION >= 3 PyModuleDef *def = new PyModuleDef(); - memset(def, 0, sizeof(PyModuleDef)); + std::memset(def, 0, sizeof(PyModuleDef)); def->m_name = name; def->m_doc = doc; def->m_size = -1; @@ -766,21 +848,36 @@ public: return reinterpret_steal<module>(obj); } + /// Reload the module or throws `error_already_set`. + void reload() { + PyObject *obj = PyImport_ReloadModule(ptr()); + if (!obj) + throw error_already_set(); + *this = reinterpret_steal<module>(obj); + } + // Adds an object to the module using the given name. Throws if an object with the given name // already exists. // // overwrite should almost always be false: attempting to overwrite objects that pybind11 has // established will, in most cases, break things. - PYBIND11_NOINLINE void add_object(const char *name, object &obj, bool overwrite = false) { + PYBIND11_NOINLINE void add_object(const char *name, handle obj, bool overwrite = false) { if (!overwrite && hasattr(*this, name)) pybind11_fail("Error during initialization: multiple incompatible definitions with name \"" + std::string(name) + "\""); - obj.inc_ref(); // PyModule_AddObject() steals a reference - PyModule_AddObject(ptr(), name, obj.ptr()); + PyModule_AddObject(ptr(), name, obj.inc_ref().ptr() /* steals a reference */); } }; +/// \ingroup python_builtins +/// Return a dictionary representing the global variables in the current execution frame, +/// or ``__main__.__dict__`` if there is no frame (usually when the interpreter is embedded). +inline dict globals() { + PyObject *p = PyEval_GetGlobals(); + return reinterpret_borrow<dict>(p ? p : module::import("__main__").attr("__dict__").ptr()); +} + NAMESPACE_BEGIN(detail) /// Generic support for creating new Python heap types class generic_type : public object { @@ -793,7 +890,7 @@ protected: pybind11_fail("generic_type: cannot initialize type \"" + std::string(rec.name) + "\": an object with that name is already defined"); - if (get_type_info(*rec.type)) + if (rec.module_local ? get_local_type_info(*rec.type) : get_global_type_info(*rec.type)) pybind11_fail("generic_type: type \"" + std::string(rec.name) + "\" is already registered!"); @@ -802,20 +899,40 @@ protected: /* Register supplemental type information in C++ dict */ auto *tinfo = new detail::type_info(); tinfo->type = (PyTypeObject *) m_ptr; + tinfo->cpptype = rec.type; tinfo->type_size = rec.type_size; tinfo->operator_new = rec.operator_new; - tinfo->init_holder = rec.init_holder; + tinfo->holder_size_in_ptrs = size_in_ptrs(rec.holder_size); + tinfo->init_instance = rec.init_instance; tinfo->dealloc = rec.dealloc; + tinfo->simple_type = true; + tinfo->simple_ancestors = true; + tinfo->default_holder = rec.default_holder; + tinfo->module_local = rec.module_local; auto &internals = get_internals(); auto tindex = std::type_index(*rec.type); tinfo->direct_conversions = &internals.direct_conversions[tindex]; - tinfo->default_holder = rec.default_holder; - internals.registered_types_cpp[tindex] = tinfo; - internals.registered_types_py[m_ptr] = tinfo; + if (rec.module_local) + registered_local_types_cpp()[tindex] = tinfo; + else + internals.registered_types_cpp[tindex] = tinfo; + internals.registered_types_py[(PyTypeObject *) m_ptr] = { tinfo }; - if (rec.bases.size() > 1 || rec.multiple_inheritance) + if (rec.bases.size() > 1 || rec.multiple_inheritance) { mark_parents_nonsimple(tinfo->type); + tinfo->simple_ancestors = false; + } + else if (rec.bases.size() == 1) { + auto parent_tinfo = get_type_info((PyTypeObject *) rec.bases[0].ptr()); + tinfo->simple_ancestors = parent_tinfo->simple_ancestors; + } + + if (rec.module_local) { + // Stash the local typeinfo and loader so that external modules can access it. + tinfo->module_local_load = &type_caster_generic::local_load; + setattr(m_ptr, PYBIND11_MODULE_LOCAL_ID, capsule(tinfo)); + } } /// Helper function which tags all parents of a type using mult. inheritance @@ -867,33 +984,54 @@ void set_operator_new(type_record *r) { r->operator_new = &T::operator new; } template <typename> void set_operator_new(...) { } +template <typename T, typename SFINAE = void> struct has_operator_delete : std::false_type { }; +template <typename T> struct has_operator_delete<T, void_t<decltype(static_cast<void (*)(void *)>(T::operator delete))>> + : std::true_type { }; +template <typename T, typename SFINAE = void> struct has_operator_delete_size : std::false_type { }; +template <typename T> struct has_operator_delete_size<T, void_t<decltype(static_cast<void (*)(void *, size_t)>(T::operator delete))>> + : std::true_type { }; /// Call class-specific delete if it exists or global otherwise. Can also be an overload set. -template <typename T, typename = void_t<decltype(static_cast<void (*)(void *)>(T::operator delete))>> -void call_operator_delete(T *p) { T::operator delete(p); } +template <typename T, enable_if_t<has_operator_delete<T>::value, int> = 0> +void call_operator_delete(T *p, size_t) { T::operator delete(p); } +template <typename T, enable_if_t<!has_operator_delete<T>::value && has_operator_delete_size<T>::value, int> = 0> +void call_operator_delete(T *p, size_t s) { T::operator delete(p, s); } -inline void call_operator_delete(void *p) { ::operator delete(p); } +inline void call_operator_delete(void *p, size_t) { ::operator delete(p); } NAMESPACE_END(detail) +/// Given a pointer to a member function, cast it to its `Derived` version. +/// Forward everything else unchanged. +template <typename /*Derived*/, typename F> +auto method_adaptor(F &&f) -> decltype(std::forward<F>(f)) { return std::forward<F>(f); } + +template <typename Derived, typename Return, typename Class, typename... Args> +auto method_adaptor(Return (Class::*pmf)(Args...)) -> Return (Derived::*)(Args...) { return pmf; } + +template <typename Derived, typename Return, typename Class, typename... Args> +auto method_adaptor(Return (Class::*pmf)(Args...) const) -> Return (Derived::*)(Args...) const { return pmf; } + template <typename type_, typename... options> class class_ : public detail::generic_type { template <typename T> using is_holder = detail::is_holder_type<type_, T>; - template <typename T> using is_subtype = detail::bool_constant<std::is_base_of<type_, T>::value && !std::is_same<T, type_>::value>; - template <typename T> using is_base = detail::bool_constant<std::is_base_of<T, type_>::value && !std::is_same<T, type_>::value>; + template <typename T> using is_subtype = detail::is_strict_base_of<type_, T>; + template <typename T> using is_base = detail::is_strict_base_of<T, type_>; // struct instead of using here to help MSVC: template <typename T> struct is_valid_class_option : detail::any_of<is_holder<T>, is_subtype<T>, is_base<T>> {}; public: using type = type_; - using type_alias = detail::first_of_t<is_subtype, void, options...>; + using type_alias = detail::exactly_one_t<is_subtype, void, options...>; constexpr static bool has_alias = !std::is_void<type_alias>::value; - using holder_type = detail::first_of_t<is_holder, std::unique_ptr<type>, options...>; - using instance_type = detail::instance<type, holder_type>; + using holder_type = detail::exactly_one_t<is_holder, std::unique_ptr<type>, options...>; static_assert(detail::all_of<is_valid_class_option<options>...>::value, "Unknown/invalid class_ template parameters provided"); + static_assert(!has_alias || std::is_polymorphic<type>::value, + "Cannot use an alias class with a non-polymorphic type"); + PYBIND11_OBJECT(class_, generic_type, PyType_Check) template <typename... Extra> @@ -913,16 +1051,15 @@ public: record.name = name; record.type = &typeid(type); record.type_size = sizeof(conditional_t<has_alias, type_alias, type>); - record.instance_size = sizeof(instance_type); - record.init_holder = init_holder; + record.holder_size = sizeof(holder_type); + record.init_instance = init_instance; record.dealloc = dealloc; record.default_holder = std::is_same<holder_type, std::unique_ptr<type>>::value; set_operator_new<type>(&record); /* Register base classes specified via template arguments to class_, if any */ - bool unused[] = { (add_base<options>(record), false)..., false }; - (void) unused; + PYBIND11_EXPAND_SIDE_EFFECTS(add_base<options>(record)); /* Process optional arguments, if any */ process_attributes<Extra...>::init(extra..., &record); @@ -930,14 +1067,14 @@ public: generic_type::initialize(record); if (has_alias) { - auto &instances = get_internals().registered_types_cpp; + auto &instances = record.module_local ? registered_local_types_cpp() : get_internals().registered_types_cpp; instances[std::type_index(typeid(type_alias))] = instances[std::type_index(typeid(type))]; } } template <typename Base, detail::enable_if_t<is_base<Base>::value, int> = 0> static void add_base(detail::type_record &rec) { - rec.add_base(&typeid(Base), [](void *src) -> void * { + rec.add_base(typeid(Base), [](void *src) -> void * { return static_cast<Base *>(reinterpret_cast<type *>(src)); }); } @@ -947,7 +1084,7 @@ public: template <typename Func, typename... Extra> class_ &def(const char *name_, Func&& f, const Extra&... extra) { - cpp_function cf(std::forward<Func>(f), name(name_), is_method(*this), + cpp_function cf(method_adaptor<type>(std::forward<Func>(f)), name(name_), is_method(*this), sibling(getattr(*this, name_, none())), extra...); attr(cf.name()) = cf; return *this; @@ -976,17 +1113,29 @@ public: } template <typename... Args, typename... Extra> - class_ &def(const detail::init<Args...> &init, const Extra&... extra) { + class_ &def(const detail::initimpl::constructor<Args...> &init, const Extra&... extra) { init.execute(*this, extra...); return *this; } template <typename... Args, typename... Extra> - class_ &def(const detail::init_alias<Args...> &init, const Extra&... extra) { + class_ &def(const detail::initimpl::alias_constructor<Args...> &init, const Extra&... extra) { init.execute(*this, extra...); return *this; } + template <typename... Args, typename... Extra> + class_ &def(detail::initimpl::factory<Args...> &&init, const Extra&... extra) { + std::move(init).execute(*this, extra...); + return *this; + } + + template <typename... Args, typename... Extra> + class_ &def(detail::initimpl::pickle_factory<Args...> &&pf, const Extra &...extra) { + std::move(pf).execute(*this, extra...); + return *this; + } + template <typename Func> class_& def_buffer(Func &&func) { struct capture { Func func; }; capture *ptr = new capture { std::forward<Func>(func) }; @@ -999,17 +1148,29 @@ public: return *this; } + template <typename Return, typename Class, typename... Args> + class_ &def_buffer(Return (Class::*func)(Args...)) { + return def_buffer([func] (type &obj) { return (obj.*func)(); }); + } + + template <typename Return, typename Class, typename... Args> + class_ &def_buffer(Return (Class::*func)(Args...) const) { + return def_buffer([func] (const type &obj) { return (obj.*func)(); }); + } + template <typename C, typename D, typename... Extra> class_ &def_readwrite(const char *name, D C::*pm, const Extra&... extra) { - cpp_function fget([pm](const C &c) -> const D &{ return c.*pm; }, is_method(*this)), - fset([pm](C &c, const D &value) { c.*pm = value; }, is_method(*this)); + static_assert(std::is_base_of<C, type>::value, "def_readwrite() requires a class member (or base class member)"); + cpp_function fget([pm](const type &c) -> const D &{ return c.*pm; }, is_method(*this)), + fset([pm](type &c, const D &value) { c.*pm = value; }, is_method(*this)); def_property(name, fget, fset, return_value_policy::reference_internal, extra...); return *this; } template <typename C, typename D, typename... Extra> class_ &def_readonly(const char *name, const D C::*pm, const Extra& ...extra) { - cpp_function fget([pm](const C &c) -> const D &{ return c.*pm; }, is_method(*this)); + static_assert(std::is_base_of<C, type>::value, "def_readonly() requires a class member (or base class member)"); + cpp_function fget([pm](const type &c) -> const D &{ return c.*pm; }, is_method(*this)); def_property_readonly(name, fget, return_value_policy::reference_internal, extra...); return *this; } @@ -1032,7 +1193,8 @@ public: /// Uses return_value_policy::reference_internal by default template <typename Getter, typename... Extra> class_ &def_property_readonly(const char *name, const Getter &fget, const Extra& ...extra) { - return def_property_readonly(name, cpp_function(fget), return_value_policy::reference_internal, extra...); + return def_property_readonly(name, cpp_function(method_adaptor<type>(fget)), + return_value_policy::reference_internal, extra...); } /// Uses cpp_function's return_value_policy by default @@ -1054,9 +1216,14 @@ public: } /// Uses return_value_policy::reference_internal by default + template <typename Getter, typename Setter, typename... Extra> + class_ &def_property(const char *name, const Getter &fget, const Setter &fset, const Extra& ...extra) { + return def_property(name, fget, cpp_function(method_adaptor<type>(fset)), extra...); + } template <typename Getter, typename... Extra> class_ &def_property(const char *name, const Getter &fget, const cpp_function &fset, const Extra& ...extra) { - return def_property(name, cpp_function(fget), fset, return_value_policy::reference_internal, extra...); + return def_property(name, cpp_function(method_adaptor<type>(fget)), fset, + return_value_policy::reference_internal, extra...); } /// Uses cpp_function's return_value_policy by default @@ -1096,51 +1263,68 @@ public: private: /// Initialize holder object, variant 1: object derives from enable_shared_from_this template <typename T> - static void init_holder_helper(instance_type *inst, const holder_type * /* unused */, const std::enable_shared_from_this<T> * /* dummy */) { + static void init_holder(detail::instance *inst, detail::value_and_holder &v_h, + const holder_type * /* unused */, const std::enable_shared_from_this<T> * /* dummy */) { try { - new (&inst->holder) holder_type(std::static_pointer_cast<typename holder_type::element_type>(inst->value->shared_from_this())); - inst->holder_constructed = true; - } catch (const std::bad_weak_ptr &) { - if (inst->owned) { - new (&inst->holder) holder_type(inst->value); - inst->holder_constructed = true; + auto sh = std::dynamic_pointer_cast<typename holder_type::element_type>( + v_h.value_ptr<type>()->shared_from_this()); + if (sh) { + new (&v_h.holder<holder_type>()) holder_type(std::move(sh)); + v_h.set_holder_constructed(); } + } catch (const std::bad_weak_ptr &) {} + + if (!v_h.holder_constructed() && inst->owned) { + new (&v_h.holder<holder_type>()) holder_type(v_h.value_ptr<type>()); + v_h.set_holder_constructed(); } } - static void init_holder_from_existing(instance_type *inst, const holder_type *holder_ptr, - std::true_type /*is_copy_constructible*/) { - new (&inst->holder) holder_type(*holder_ptr); + static void init_holder_from_existing(const detail::value_and_holder &v_h, + const holder_type *holder_ptr, std::true_type /*is_copy_constructible*/) { + new (&v_h.holder<holder_type>()) holder_type(*reinterpret_cast<const holder_type *>(holder_ptr)); } - static void init_holder_from_existing(instance_type *inst, const holder_type *holder_ptr, - std::false_type /*is_copy_constructible*/) { - new (&inst->holder) holder_type(std::move(*const_cast<holder_type *>(holder_ptr))); + static void init_holder_from_existing(const detail::value_and_holder &v_h, + const holder_type *holder_ptr, std::false_type /*is_copy_constructible*/) { + new (&v_h.holder<holder_type>()) holder_type(std::move(*const_cast<holder_type *>(holder_ptr))); } /// Initialize holder object, variant 2: try to construct from existing holder object, if possible - static void init_holder_helper(instance_type *inst, const holder_type *holder_ptr, const void * /* dummy */) { + static void init_holder(detail::instance *inst, detail::value_and_holder &v_h, + const holder_type *holder_ptr, const void * /* dummy -- not enable_shared_from_this<T>) */) { if (holder_ptr) { - init_holder_from_existing(inst, holder_ptr, std::is_copy_constructible<holder_type>()); - inst->holder_constructed = true; + init_holder_from_existing(v_h, holder_ptr, std::is_copy_constructible<holder_type>()); + v_h.set_holder_constructed(); } else if (inst->owned || detail::always_construct_holder<holder_type>::value) { - new (&inst->holder) holder_type(inst->value); - inst->holder_constructed = true; + new (&v_h.holder<holder_type>()) holder_type(v_h.value_ptr<type>()); + v_h.set_holder_constructed(); } } - /// Initialize holder object of an instance, possibly given a pointer to an existing holder - static void init_holder(PyObject *inst_, const void *holder_ptr) { - auto inst = (instance_type *) inst_; - init_holder_helper(inst, (const holder_type *) holder_ptr, inst->value); + /// Performs instance initialization including constructing a holder and registering the known + /// instance. Should be called as soon as the `type` value_ptr is set for an instance. Takes an + /// optional pointer to an existing holder to use; if not specified and the instance is + /// `.owned`, a new holder will be constructed to manage the value pointer. + static void init_instance(detail::instance *inst, const void *holder_ptr) { + auto v_h = inst->get_value_and_holder(detail::get_type_info(typeid(type))); + if (!v_h.instance_registered()) { + register_instance(inst, v_h.value_ptr(), v_h.type); + v_h.set_instance_registered(); + } + init_holder(inst, v_h, (const holder_type *) holder_ptr, v_h.value_ptr<type>()); } - static void dealloc(PyObject *inst_) { - instance_type *inst = (instance_type *) inst_; - if (inst->holder_constructed) - inst->holder.~holder_type(); - else if (inst->owned) - detail::call_operator_delete(inst->value); + /// Deallocates an instance; via holder, if constructed; otherwise via operator delete. + static void dealloc(detail::value_and_holder &v_h) { + if (v_h.holder_constructed()) { + v_h.holder<holder_type>().~holder_type(); + v_h.set_holder_constructed(false); + } + else { + detail::call_operator_delete(v_h.value_ptr<type>(), v_h.type->type_size); + } + v_h.value_ptr() = nullptr; } static detail::function_record *get_function_record(handle h) { @@ -1150,21 +1334,42 @@ private: } }; +/// Binds an existing constructor taking arguments Args... +template <typename... Args> detail::initimpl::constructor<Args...> init() { return {}; } +/// Like `init<Args...>()`, but the instance is always constructed through the alias class (even +/// when not inheriting on the Python side). +template <typename... Args> detail::initimpl::alias_constructor<Args...> init_alias() { return {}; } + +/// Binds a factory function as a constructor +template <typename Func, typename Ret = detail::initimpl::factory<Func>> +Ret init(Func &&f) { return {std::forward<Func>(f)}; } + +/// Dual-argument factory function: the first function is called when no alias is needed, the second +/// when an alias is needed (i.e. due to python-side inheritance). Arguments must be identical. +template <typename CFunc, typename AFunc, typename Ret = detail::initimpl::factory<CFunc, AFunc>> +Ret init(CFunc &&c, AFunc &&a) { + return {std::forward<CFunc>(c), std::forward<AFunc>(a)}; +} + +/// Binds pickling functions `__getstate__` and `__setstate__` and ensures that the type +/// returned by `__getstate__` is the same as the argument accepted by `__setstate__`. +template <typename GetState, typename SetState> +detail::initimpl::pickle_factory<GetState, SetState> pickle(GetState &&g, SetState &&s) { + return {std::forward<GetState>(g), std::forward<SetState>(s)}; +} + /// Binds C++ enumerations and enumeration classes to Python template <typename Type> class enum_ : public class_<Type> { public: using class_<Type>::def; using class_<Type>::def_property_readonly_static; using Scalar = typename std::underlying_type<Type>::type; - template <typename T> using arithmetic_tag = std::is_same<T, arithmetic>; template <typename... Extra> enum_(const handle &scope, const char *name, const Extra&... extra) : class_<Type>(scope, name, extra...), m_entries(), m_parent(scope) { - constexpr bool is_arithmetic = - !std::is_same<detail::first_of_t<arithmetic_tag, void, Extra...>, - void>::value; + constexpr bool is_arithmetic = detail::any_of<std::is_same<arithmetic, Extra>...>::value; auto m_entries_ptr = m_entries.inc_ref().ptr(); def("__repr__", [name, m_entries_ptr](Type value) -> pybind11::str { @@ -1180,8 +1385,11 @@ public: m[kv.first] = kv.second; return m; }, return_value_policy::copy); - def("__init__", [](Type& value, Scalar i) { value = (Type)i; }); + def(init([](Scalar i) { return static_cast<Type>(i); })); def("__int__", [](Type value) { return (Scalar) value; }); + #if PY_MAJOR_VERSION < 3 + def("__long__", [](Type value) { return (Scalar) value; }); + #endif def("__eq__", [](const Type &value, Type *value2) { return value2 && value == *value2; }); def("__ne__", [](const Type &value, Type *value2) { return !value2 || value != *value2; }); if (is_arithmetic) { @@ -1215,8 +1423,8 @@ public: } def("__hash__", [](const Type &value) { return (Scalar) value; }); // Pickling and unpickling -- needed for use with the 'multiprocessing' module - def("__getstate__", [](const Type &value) { return pybind11::make_tuple((Scalar) value); }); - def("__setstate__", [](Type &p, tuple t) { new (&p) Type((Type) t[0].cast<Scalar>()); }); + def(pickle([](const Type &value) { return pybind11::make_tuple((Scalar) value); }, + [](tuple t) { return static_cast<Type>(t[0].cast<Scalar>()); })); } /// Export enumeration entries into the parent scope @@ -1240,82 +1448,77 @@ private: }; NAMESPACE_BEGIN(detail) -template <typename... Args> struct init { - template <typename Class, typename... Extra, enable_if_t<!Class::has_alias, int> = 0> - static void execute(Class &cl, const Extra&... extra) { - using Base = typename Class::type; - /// Function which calls a specific C++ in-place constructor - cl.def("__init__", [](Base *self_, Args... args) { new (self_) Base(args...); }, extra...); - } - - template <typename Class, typename... Extra, - enable_if_t<Class::has_alias && - std::is_constructible<typename Class::type, Args...>::value, int> = 0> - static void execute(Class &cl, const Extra&... extra) { - using Base = typename Class::type; - using Alias = typename Class::type_alias; - handle cl_type = cl; - cl.def("__init__", [cl_type](handle self_, Args... args) { - if (self_.get_type() == cl_type) - new (self_.cast<Base *>()) Base(args...); - else - new (self_.cast<Alias *>()) Alias(args...); - }, extra...); - } - - template <typename Class, typename... Extra, - enable_if_t<Class::has_alias && - !std::is_constructible<typename Class::type, Args...>::value, int> = 0> - static void execute(Class &cl, const Extra&... extra) { - init_alias<Args...>::execute(cl, extra...); - } -}; -template <typename... Args> struct init_alias { - template <typename Class, typename... Extra, - enable_if_t<Class::has_alias && std::is_constructible<typename Class::type_alias, Args...>::value, int> = 0> - static void execute(Class &cl, const Extra&... extra) { - using Alias = typename Class::type_alias; - cl.def("__init__", [](Alias *self_, Args... args) { new (self_) Alias(args...); }, extra...); - } -}; inline void keep_alive_impl(handle nurse, handle patient) { - /* Clever approach based on weak references taken from Boost.Python */ if (!nurse || !patient) pybind11_fail("Could not activate keep_alive!"); if (patient.is_none() || nurse.is_none()) return; /* Nothing to keep alive or nothing to be kept alive by */ - cpp_function disable_lifesupport( - [patient](handle weakref) { patient.dec_ref(); weakref.dec_ref(); }); + auto tinfo = all_type_info(Py_TYPE(nurse.ptr())); + if (!tinfo.empty()) { + /* It's a pybind-registered type, so we can store the patient in the + * internal list. */ + add_patient(nurse.ptr(), patient.ptr()); + } + else { + /* Fall back to clever approach based on weak references taken from + * Boost.Python. This is not used for pybind-registered types because + * the objects can be destroyed out-of-order in a GC pass. */ + cpp_function disable_lifesupport( + [patient](handle weakref) { patient.dec_ref(); weakref.dec_ref(); }); - weakref wr(nurse, disable_lifesupport); + weakref wr(nurse, disable_lifesupport); - patient.inc_ref(); /* reference patient and leak the weak reference */ - (void) wr.release(); + patient.inc_ref(); /* reference patient and leak the weak reference */ + (void) wr.release(); + } } PYBIND11_NOINLINE inline void keep_alive_impl(size_t Nurse, size_t Patient, function_call &call, handle ret) { - keep_alive_impl( - Nurse == 0 ? ret : Nurse <= call.args.size() ? call.args[Nurse - 1] : handle(), - Patient == 0 ? ret : Patient <= call.args.size() ? call.args[Patient - 1] : handle() - ); + auto get_arg = [&](size_t n) { + if (n == 0) + return ret; + else if (n == 1 && call.init_self) + return call.init_self; + else if (n <= call.args.size()) + return call.args[n - 1]; + return handle(); + }; + + keep_alive_impl(get_arg(Nurse), get_arg(Patient)); +} + +inline std::pair<decltype(internals::registered_types_py)::iterator, bool> all_type_info_get_cache(PyTypeObject *type) { + auto res = get_internals().registered_types_py +#ifdef __cpp_lib_unordered_map_try_emplace + .try_emplace(type); +#else + .emplace(type, std::vector<detail::type_info *>()); +#endif + if (res.second) { + // New cache entry created; set up a weak reference to automatically remove it if the type + // gets destroyed: + weakref((PyObject *) type, cpp_function([type](handle wr) { + get_internals().registered_types_py.erase(type); + wr.dec_ref(); + })).release(); + } + + return res; } template <typename Iterator, typename Sentinel, bool KeyIterator, return_value_policy Policy> struct iterator_state { Iterator it; Sentinel end; - bool first; + bool first_or_done; }; NAMESPACE_END(detail) -template <typename... Args> detail::init<Args...> init() { return detail::init<Args...>(); } -template <typename... Args> detail::init_alias<Args...> init_alias() { return detail::init_alias<Args...>(); } - /// Makes a python iterator from a first and past-the-end C++ InputIterator. template <return_value_policy Policy = return_value_policy::reference_internal, typename Iterator, @@ -1326,20 +1529,22 @@ iterator make_iterator(Iterator first, Sentinel last, Extra &&... extra) { typedef detail::iterator_state<Iterator, Sentinel, false, Policy> state; if (!detail::get_type_info(typeid(state), false)) { - class_<state>(handle(), "iterator") + class_<state>(handle(), "iterator", pybind11::module_local()) .def("__iter__", [](state &s) -> state& { return s; }) .def("__next__", [](state &s) -> ValueType { - if (!s.first) + if (!s.first_or_done) ++s.it; else - s.first = false; - if (s.it == s.end) + s.first_or_done = false; + if (s.it == s.end) { + s.first_or_done = true; throw stop_iteration(); + } return *s.it; }, std::forward<Extra>(extra)..., Policy); } - return (iterator) cast(state { first, last, true }); + return cast(state{first, last, true}); } /// Makes an python iterator over the keys (`.first`) of a iterator over pairs from a @@ -1353,20 +1558,22 @@ iterator make_key_iterator(Iterator first, Sentinel last, Extra &&... extra) { typedef detail::iterator_state<Iterator, Sentinel, true, Policy> state; if (!detail::get_type_info(typeid(state), false)) { - class_<state>(handle(), "iterator") + class_<state>(handle(), "iterator", pybind11::module_local()) .def("__iter__", [](state &s) -> state& { return s; }) .def("__next__", [](state &s) -> KeyType { - if (!s.first) + if (!s.first_or_done) ++s.it; else - s.first = false; - if (s.it == s.end) + s.first_or_done = false; + if (s.it == s.end) { + s.first_or_done = true; throw stop_iteration(); + } return (*s.it).first; }, std::forward<Extra>(extra)..., Policy); } - return (iterator) cast(state { first, last, true }); + return cast(state{first, last, true}); } /// Makes an iterator over values of an stl container or other container supporting @@ -1384,7 +1591,16 @@ template <return_value_policy Policy = return_value_policy::reference_internal, } template <typename InputType, typename OutputType> void implicitly_convertible() { + struct set_flag { + bool &flag; + set_flag(bool &flag) : flag(flag) { flag = true; } + ~set_flag() { flag = false; } + }; auto implicit_caster = [](PyObject *obj, PyTypeObject *type) -> PyObject * { + static bool currently_used = false; + if (currently_used) // implicit conversions are non-reentrant + return nullptr; + set_flag flag_helper(currently_used); if (!detail::make_caster<InputType>().load(obj, false)) return nullptr; tuple args(1); @@ -1407,7 +1623,8 @@ void register_exception_translator(ExceptionTranslator&& translator) { std::forward<ExceptionTranslator>(translator)); } -/* Wrapper to generate a new Python exception type. +/** + * Wrapper to generate a new Python exception type. * * This should only be used with PyErr_SetString for now. * It is not (yet) possible to use as a py::base. @@ -1432,7 +1649,8 @@ public: } }; -/** Registers a Python exception in `m` of the given `name` and installs an exception translator to +/** + * Registers a Python exception in `m` of the given `name` and installs an exception translator to * translate the C++ exception to the created Python exception using the exceptions what() method. * This is intended for simple exception translations; for more complex translation, register the * exception object and translator directly. @@ -1589,9 +1807,13 @@ private: class gil_scoped_release { public: explicit gil_scoped_release(bool disassoc = false) : disassoc(disassoc) { + // `get_internals()` must be called here unconditionally in order to initialize + // `internals.tstate` for subsequent `gil_scoped_acquire` calls. Otherwise, an + // initialization race could occur as multiple threads try `gil_scoped_acquire`. + const auto &internals = detail::get_internals(); tstate = PyEval_SaveThread(); if (disassoc) { - auto key = detail::get_internals().tstate; + auto key = internals.tstate; #if PY_MAJOR_VERSION < 3 PyThread_delete_key_value(key); #else @@ -1635,9 +1857,11 @@ class gil_scoped_release { }; #endif error_already_set::~error_already_set() { - if (value) { + if (type) { gil_scoped_acquire gil; - clear(); + type.release().dec_ref(); + value.release().dec_ref(); + trace.release().dec_ref(); } } @@ -1690,7 +1914,7 @@ inline function get_type_overload(const void *this_ptr, const detail::type_info Py_file_input, d.ptr(), d.ptr()); if (result == nullptr) throw error_already_set(); - if ((handle) d["self"] == Py_None) + if (d["self"].is_none()) return function(); Py_DECREF(result); #endif @@ -1730,7 +1954,7 @@ template <class T> function get_overload(const T *this_ptr, const char *name) { #define PYBIND11_OVERLOAD_PURE(ret_type, cname, fn, ...) \ PYBIND11_OVERLOAD_PURE_NAME(ret_type, cname, #fn, fn, __VA_ARGS__) -NAMESPACE_END(pybind11) +NAMESPACE_END(PYBIND11_NAMESPACE) #if defined(_MSC_VER) # pragma warning(pop) diff --git a/ext/pybind11/include/pybind11/pytypes.h b/ext/pybind11/include/pybind11/pytypes.h index 900c57564..d7fa17775 100644 --- a/ext/pybind11/include/pybind11/pytypes.h +++ b/ext/pybind11/include/pybind11/pytypes.h @@ -1,5 +1,5 @@ /* - pybind11/typeid.h: Convenience wrapper classes for basic Python types + pybind11/pytypes.h: Convenience wrapper classes for basic Python types Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch> @@ -9,11 +9,12 @@ #pragma once -#include "common.h" +#include "detail/common.h" +#include "buffer_info.h" #include <utility> #include <type_traits> -NAMESPACE_BEGIN(pybind11) +NAMESPACE_BEGIN(PYBIND11_NAMESPACE) /* A few forward declarations */ class handle; class object; @@ -43,7 +44,7 @@ using tuple_accessor = accessor<accessor_policies::tuple_item>; /// Tag and check to identify a class which implements the Python object API class pyobject_tag { }; -template <typename T> using is_pyobject = std::is_base_of<pyobject_tag, typename std::remove_reference<T>::type>; +template <typename T> using is_pyobject = std::is_base_of<pyobject_tag, remove_reference_t<T>>; /** \rst A mixin class which adds common functions to `handle`, `object` and various accessors. @@ -109,11 +110,16 @@ public: PYBIND11_DEPRECATED("call(...) was deprecated in favor of operator()(...)") object call(Args&&... args) const; + /// Equivalent to ``obj is other`` in Python. + bool is(object_api const& other) const { return derived().ptr() == other.derived().ptr(); } /// Equivalent to ``obj is None`` in Python. bool is_none() const { return derived().ptr() == Py_None; } PYBIND11_DEPRECATED("Use py::str(obj) instead") pybind11::str str() const; + /// Get or set the object's docstring, i.e. ``obj.__doc__``. + str_attr_accessor doc() const; + /// Return the object's current reference count int ref_count() const { return static_cast<int>(Py_REFCNT(derived().ptr())); } /// Return a handle to the Python type object underlying the instance @@ -166,10 +172,12 @@ public: /// Return ``true`` when the `handle` wraps a valid Python object explicit operator bool() const { return m_ptr != nullptr; } /** \rst - Check that the underlying pointers are the same. + Deprecated: Check that the underlying pointers are the same. Equivalent to ``obj1 is obj2`` in Python. \endrst */ + PYBIND11_DEPRECATED("Use obj1.is(obj2) instead") bool operator==(const handle &h) const { return m_ptr == h.m_ptr; } + PYBIND11_DEPRECATED("Use !obj1.is(obj2) instead") bool operator!=(const handle &h) const { return m_ptr != h.m_ptr; } PYBIND11_DEPRECATED("Use handle::operator bool() instead") bool check() const { return m_ptr != nullptr; } @@ -234,8 +242,8 @@ public: protected: // Tags for choosing constructors from raw PyObject * - struct borrowed_t { }; static constexpr borrowed_t borrowed{}; - struct stolen_t { }; static constexpr stolen_t stolen{}; + struct borrowed_t { }; + struct stolen_t { }; template <typename T> friend T reinterpret_borrow(handle); template <typename T> friend T reinterpret_steal(handle); @@ -259,7 +267,7 @@ public: // or py::tuple t = reinterpret_borrow<py::tuple>(p); // <-- `p` must be already be a `tuple` \endrst */ -template <typename T> T reinterpret_borrow(handle h) { return {h, object::borrowed}; } +template <typename T> T reinterpret_borrow(handle h) { return {h, object::borrowed_t{}}; } /** \rst Like `reinterpret_borrow`, but steals the reference. @@ -269,7 +277,43 @@ template <typename T> T reinterpret_borrow(handle h) { return {h, object::borrow PyObject *p = PyObject_Str(obj); py::str s = reinterpret_steal<py::str>(p); // <-- `p` must be already be a `str` \endrst */ -template <typename T> T reinterpret_steal(handle h) { return {h, object::stolen}; } +template <typename T> T reinterpret_steal(handle h) { return {h, object::stolen_t{}}; } + +NAMESPACE_BEGIN(detail) +inline std::string error_string(); +NAMESPACE_END(detail) + +/// Fetch and hold an error which was already set in Python. An instance of this is typically +/// thrown to propagate python-side errors back through C++ which can either be caught manually or +/// else falls back to the function dispatcher (which then raises the captured error back to +/// python). +class error_already_set : public std::runtime_error { +public: + /// Constructs a new exception from the current Python error indicator, if any. The current + /// Python error indicator will be cleared. + error_already_set() : std::runtime_error(detail::error_string()) { + PyErr_Fetch(&type.ptr(), &value.ptr(), &trace.ptr()); + } + + inline ~error_already_set(); + + /// Give the currently-held error back to Python, if any. If there is currently a Python error + /// already set it is cleared first. After this call, the current object no longer stores the + /// error variables (but the `.what()` string is still available). + void restore() { PyErr_Restore(type.release().ptr(), value.release().ptr(), trace.release().ptr()); } + + // Does nothing; provided for backwards compatibility. + PYBIND11_DEPRECATED("Use of error_already_set.clear() is deprecated") + void clear() {} + + /// Check if the currently trapped error type matches the given Python exception class (or a + /// subclass thereof). May also be passed a tuple to search for any exception class matches in + /// the given tuple. + bool matches(handle ex) const { return PyErr_GivenExceptionMatches(ex.ptr(), type.ptr()); } + +private: + object type, value, trace; +}; /** \defgroup python_builtins _ Unless stated otherwise, the following C++ functions behave the same @@ -346,6 +390,13 @@ inline void setattr(handle obj, handle name, handle value) { inline void setattr(handle obj, const char *name, handle value) { if (PyObject_SetAttrString(obj.ptr(), name, value.ptr()) != 0) { throw error_already_set(); } } + +inline ssize_t hash(handle obj) { + auto h = PyObject_Hash(obj.ptr()); + if (h == -1) { throw error_already_set(); } + return h; +} + /// @} python_builtins NAMESPACE_BEGIN(detail) @@ -354,6 +405,7 @@ inline handle get_function(handle value) { #if PY_MAJOR_VERSION >= 3 if (PyInstanceMethod_Check(value.ptr())) value = PyInstanceMethod_GET_FUNCTION(value.ptr()); + else #endif if (PyMethod_Check(value.ptr())) value = PyMethod_GET_FUNCTION(value.ptr()); @@ -379,6 +431,8 @@ class accessor : public object_api<accessor<Policy>> { public: accessor(handle obj, key_type key) : obj(obj), key(std::move(key)) { } + accessor(const accessor &) = default; + accessor(accessor &&) = default; // accessor overload required to override default assignment operator (templates are not allowed // to replace default compiler-generated assignments). @@ -674,9 +728,9 @@ NAMESPACE_END(detail) #define PYBIND11_OBJECT_COMMON(Name, Parent, CheckFun) \ public: \ PYBIND11_DEPRECATED("Use reinterpret_borrow<"#Name">() or reinterpret_steal<"#Name">()") \ - Name(handle h, bool is_borrowed) : Parent(is_borrowed ? Parent(h, borrowed) : Parent(h, stolen)) { } \ - Name(handle h, borrowed_t) : Parent(h, borrowed) { } \ - Name(handle h, stolen_t) : Parent(h, stolen) { } \ + Name(handle h, bool is_borrowed) : Parent(is_borrowed ? Parent(h, borrowed_t{}) : Parent(h, stolen_t{})) { } \ + Name(handle h, borrowed_t) : Parent(h, borrowed_t{}) { } \ + Name(handle h, stolen_t) : Parent(h, stolen_t{}) { } \ PYBIND11_DEPRECATED("Use py::isinstance<py::python_type>(obj) instead") \ bool check() const { return m_ptr != nullptr && (bool) CheckFun(m_ptr); } \ static bool check_(handle h) { return h.ptr() != nullptr && CheckFun(h.ptr()); } @@ -684,7 +738,14 @@ NAMESPACE_END(detail) #define PYBIND11_OBJECT_CVT(Name, Parent, CheckFun, ConvertFun) \ PYBIND11_OBJECT_COMMON(Name, Parent, CheckFun) \ /* This is deliberately not 'explicit' to allow implicit conversion from object: */ \ - Name(const object &o) : Parent(ConvertFun(o.ptr()), stolen) { if (!m_ptr) throw error_already_set(); } + Name(const object &o) \ + : Parent(check_(o) ? o.inc_ref().ptr() : ConvertFun(o.ptr()), stolen_t{}) \ + { if (!m_ptr) throw error_already_set(); } \ + Name(object &&o) \ + : Parent(check_(o) ? o.release().ptr() : ConvertFun(o.ptr()), stolen_t{}) \ + { if (!m_ptr) throw error_already_set(); } \ + template <typename Policy_> \ + Name(const ::pybind11::detail::accessor<Policy_> &a) : Name(object(a)) { } #define PYBIND11_OBJECT(Name, Parent, CheckFun) \ PYBIND11_OBJECT_COMMON(Name, Parent, CheckFun) \ @@ -778,13 +839,13 @@ public: PYBIND11_OBJECT_CVT(str, object, detail::PyUnicode_Check_Permissive, raw_str) str(const char *c, size_t n) - : object(PyUnicode_FromStringAndSize(c, (ssize_t) n), stolen) { + : object(PyUnicode_FromStringAndSize(c, (ssize_t) n), stolen_t{}) { if (!m_ptr) pybind11_fail("Could not allocate string object!"); } // 'explicit' is explicitly omitted from the following constructors to allow implicit conversion to py::str from C++ string-like objects str(const char *c = "") - : object(PyUnicode_FromString(c), stolen) { + : object(PyUnicode_FromString(c), stolen_t{}) { if (!m_ptr) pybind11_fail("Could not allocate string object!"); } @@ -796,7 +857,7 @@ public: Return a string representation of the object. This is analogous to the ``str()`` function in Python. \endrst */ - explicit str(handle h) : object(raw_str(h.ptr()), stolen) { } + explicit str(handle h) : object(raw_str(h.ptr()), stolen_t{}) { } operator std::string() const { object temp = *this; @@ -846,12 +907,12 @@ public: // Allow implicit conversion: bytes(const char *c = "") - : object(PYBIND11_BYTES_FROM_STRING(c), stolen) { + : object(PYBIND11_BYTES_FROM_STRING(c), stolen_t{}) { if (!m_ptr) pybind11_fail("Could not allocate bytes object!"); } bytes(const char *c, size_t n) - : object(PYBIND11_BYTES_FROM_STRING_AND_SIZE(c, (ssize_t) n), stolen) { + : object(PYBIND11_BYTES_FROM_STRING_AND_SIZE(c, (ssize_t) n), stolen_t{}) { if (!m_ptr) pybind11_fail("Could not allocate bytes object!"); } @@ -900,15 +961,15 @@ inline str::str(const bytes& b) { class none : public object { public: PYBIND11_OBJECT(none, object, detail::PyNone_Check) - none() : object(Py_None, borrowed) { } + none() : object(Py_None, borrowed_t{}) { } }; class bool_ : public object { public: PYBIND11_OBJECT_CVT(bool_, object, PyBool_Check, raw_bool) - bool_() : object(Py_False, borrowed) { } + bool_() : object(Py_False, borrowed_t{}) { } // Allow implicit conversion from and to `bool`: - bool_(bool value) : object(value ? Py_True : Py_False, borrowed) { } + bool_(bool value) : object(value ? Py_True : Py_False, borrowed_t{}) { } operator bool() const { return m_ptr && PyLong_AsLong(m_ptr) != 0; } private: @@ -920,10 +981,32 @@ private: } }; +NAMESPACE_BEGIN(detail) +// Converts a value to the given unsigned type. If an error occurs, you get back (Unsigned) -1; +// otherwise you get back the unsigned long or unsigned long long value cast to (Unsigned). +// (The distinction is critically important when casting a returned -1 error value to some other +// unsigned type: (A)-1 != (B)-1 when A and B are unsigned types of different sizes). +template <typename Unsigned> +Unsigned as_unsigned(PyObject *o) { + if (sizeof(Unsigned) <= sizeof(unsigned long) +#if PY_VERSION_HEX < 0x03000000 + || PyInt_Check(o) +#endif + ) { + unsigned long v = PyLong_AsUnsignedLong(o); + return v == (unsigned long) -1 && PyErr_Occurred() ? (Unsigned) -1 : (Unsigned) v; + } + else { + unsigned long long v = PyLong_AsUnsignedLongLong(o); + return v == (unsigned long long) -1 && PyErr_Occurred() ? (Unsigned) -1 : (Unsigned) v; + } +} +NAMESPACE_END(detail) + class int_ : public object { public: PYBIND11_OBJECT_CVT(int_, object, PYBIND11_LONG_CHECK, PyNumber_Long) - int_() : object(PyLong_FromLong(0), stolen) { } + int_() : object(PyLong_FromLong(0), stolen_t{}) { } // Allow implicit conversion from C++ integral types: template <typename T, detail::enable_if_t<std::is_integral<T>::value, int> = 0> @@ -945,17 +1028,11 @@ public: template <typename T, detail::enable_if_t<std::is_integral<T>::value, int> = 0> operator T() const { - if (sizeof(T) <= sizeof(long)) { - if (std::is_signed<T>::value) - return (T) PyLong_AsLong(m_ptr); - else - return (T) PyLong_AsUnsignedLong(m_ptr); - } else { - if (std::is_signed<T>::value) - return (T) PYBIND11_LONG_AS_LONGLONG(m_ptr); - else - return (T) PYBIND11_LONG_AS_UNSIGNED_LONGLONG(m_ptr); - } + return std::is_unsigned<T>::value + ? detail::as_unsigned<T>(m_ptr) + : sizeof(T) <= sizeof(long) + ? (T) PyLong_AsLong(m_ptr) + : (T) PYBIND11_LONG_AS_LONGLONG(m_ptr); } }; @@ -963,10 +1040,10 @@ class float_ : public object { public: PYBIND11_OBJECT_CVT(float_, object, PyFloat_Check, PyNumber_Float) // Allow implicit conversion from float/double: - float_(float value) : object(PyFloat_FromDouble((double) value), stolen) { + float_(float value) : object(PyFloat_FromDouble((double) value), stolen_t{}) { if (!m_ptr) pybind11_fail("Could not allocate float object!"); } - float_(double value = .0) : object(PyFloat_FromDouble((double) value), stolen) { + float_(double value = .0) : object(PyFloat_FromDouble((double) value), stolen_t{}) { if (!m_ptr) pybind11_fail("Could not allocate float object!"); } operator float() const { return (float) PyFloat_AsDouble(m_ptr); } @@ -977,7 +1054,7 @@ class weakref : public object { public: PYBIND11_OBJECT_DEFAULT(weakref, object, PyWeakref_Check) explicit weakref(handle obj, handle callback = {}) - : object(PyWeakref_NewRef(obj.ptr(), callback.ptr()), stolen) { + : object(PyWeakref_NewRef(obj.ptr(), callback.ptr()), stolen_t{}) { if (!m_ptr) pybind11_fail("Could not allocate weak reference!"); } }; @@ -1003,17 +1080,17 @@ class capsule : public object { public: PYBIND11_OBJECT_DEFAULT(capsule, object, PyCapsule_CheckExact) PYBIND11_DEPRECATED("Use reinterpret_borrow<capsule>() or reinterpret_steal<capsule>()") - capsule(PyObject *ptr, bool is_borrowed) : object(is_borrowed ? object(ptr, borrowed) : object(ptr, stolen)) { } + capsule(PyObject *ptr, bool is_borrowed) : object(is_borrowed ? object(ptr, borrowed_t{}) : object(ptr, stolen_t{})) { } - explicit capsule(const void *value) - : object(PyCapsule_New(const_cast<void *>(value), nullptr, nullptr), stolen) { + explicit capsule(const void *value, const char *name = nullptr, void (*destructor)(PyObject *) = nullptr) + : object(PyCapsule_New(const_cast<void *>(value), name, destructor), stolen_t{}) { if (!m_ptr) pybind11_fail("Could not allocate capsule object!"); } PYBIND11_DEPRECATED("Please pass a destructor that takes a void pointer as input") capsule(const void *value, void (*destruct)(PyObject *)) - : object(PyCapsule_New(const_cast<void*>(value), nullptr, destruct), stolen) { + : object(PyCapsule_New(const_cast<void*>(value), nullptr, destruct), stolen_t{}) { if (!m_ptr) pybind11_fail("Could not allocate capsule object!"); } @@ -1043,16 +1120,19 @@ public: } template <typename T> operator T *() const { - T * result = static_cast<T *>(PyCapsule_GetPointer(m_ptr, nullptr)); + auto name = this->name(); + T * result = static_cast<T *>(PyCapsule_GetPointer(m_ptr, name)); if (!result) pybind11_fail("Unable to extract capsule contents!"); return result; } + + const char *name() const { return PyCapsule_GetName(m_ptr); } }; class tuple : public object { public: PYBIND11_OBJECT_CVT(tuple, object, PyTuple_Check, PySequence_Tuple) - explicit tuple(size_t size = 0) : object(PyTuple_New((ssize_t) size), stolen) { + explicit tuple(size_t size = 0) : object(PyTuple_New((ssize_t) size), stolen_t{}) { if (!m_ptr) pybind11_fail("Could not allocate tuple object!"); } size_t size() const { return (size_t) PyTuple_Size(m_ptr); } @@ -1064,7 +1144,7 @@ public: class dict : public object { public: PYBIND11_OBJECT_CVT(dict, object, PyDict_Check, raw_dict) - dict() : object(PyDict_New(), stolen) { + dict() : object(PyDict_New(), stolen_t{}) { if (!m_ptr) pybind11_fail("Could not allocate dict object!"); } template <typename... Args, @@ -1101,7 +1181,7 @@ public: class list : public object { public: PYBIND11_OBJECT_CVT(list, object, PyList_Check, PySequence_List) - explicit list(size_t size = 0) : object(PyList_New((ssize_t) size), stolen) { + explicit list(size_t size = 0) : object(PyList_New((ssize_t) size), stolen_t{}) { if (!m_ptr) pybind11_fail("Could not allocate list object!"); } size_t size() const { return (size_t) PyList_Size(m_ptr); } @@ -1119,7 +1199,7 @@ class kwargs : public dict { PYBIND11_OBJECT_DEFAULT(kwargs, dict, PyDict_Check) class set : public object { public: PYBIND11_OBJECT_CVT(set, object, PySet_Check, PySet_New) - set() : object(PySet_New(nullptr), stolen) { + set() : object(PySet_New(nullptr), stolen_t{}) { if (!m_ptr) pybind11_fail("Could not allocate set object!"); } size_t size() const { return (size_t) PySet_Size(m_ptr); } @@ -1132,10 +1212,13 @@ public: class function : public object { public: PYBIND11_OBJECT_DEFAULT(function, object, PyCallable_Check) - bool is_cpp_function() const { + handle cpp_function() const { handle fun = detail::get_function(m_ptr); - return fun && PyCFunction_Check(fun.ptr()); + if (fun && PyCFunction_Check(fun.ptr())) + return fun; + return handle(); } + bool is_cpp_function() const { return (bool) cpp_function(); } }; class buffer : public object { @@ -1146,8 +1229,10 @@ public: int flags = PyBUF_STRIDES | PyBUF_FORMAT; if (writable) flags |= PyBUF_WRITABLE; Py_buffer *view = new Py_buffer(); - if (PyObject_GetBuffer(m_ptr, view, flags) != 0) + if (PyObject_GetBuffer(m_ptr, view, flags) != 0) { + delete view; throw error_already_set(); + } return buffer_info(view); } }; @@ -1160,15 +1245,15 @@ public: static std::vector<Py_ssize_t> py_strides { }; static std::vector<Py_ssize_t> py_shape { }; buf.buf = info.ptr; - buf.itemsize = (Py_ssize_t) info.itemsize; + buf.itemsize = info.itemsize; buf.format = const_cast<char *>(info.format.c_str()); buf.ndim = (int) info.ndim; - buf.len = (Py_ssize_t) info.size; + buf.len = info.size; py_strides.clear(); py_shape.clear(); - for (size_t i = 0; i < info.ndim; ++i) { - py_strides.push_back((Py_ssize_t) info.strides[i]); - py_shape.push_back((Py_ssize_t) info.shape[i]); + for (size_t i = 0; i < (size_t) info.ndim; ++i) { + py_strides.push_back(info.strides[i]); + py_shape.push_back(info.shape[i]); } buf.strides = py_strides.data(); buf.shape = py_shape.data(); @@ -1238,7 +1323,10 @@ template <typename D> pybind11::str object_api<D>::str() const { return pybind11::str(derived()); } template <typename D> +str_attr_accessor object_api<D>::doc() const { return attr("__doc__"); } + +template <typename D> handle object_api<D>::get_type() const { return (PyObject *) Py_TYPE(derived().ptr()); } NAMESPACE_END(detail) -NAMESPACE_END(pybind11) +NAMESPACE_END(PYBIND11_NAMESPACE) diff --git a/ext/pybind11/include/pybind11/stl.h b/ext/pybind11/include/pybind11/stl.h index 37b6bcde3..44abb8c6c 100644 --- a/ext/pybind11/include/pybind11/stl.h +++ b/ext/pybind11/include/pybind11/stl.h @@ -32,15 +32,36 @@ // std::experimental::optional (but not allowed in c++11 mode) # if defined(PYBIND11_CPP14) && __has_include(<experimental/optional>) # include <experimental/optional> -# if __cpp_lib_experimental_optional // just in case -# define PYBIND11_HAS_EXP_OPTIONAL 1 -# endif +# define PYBIND11_HAS_EXP_OPTIONAL 1 # endif +// std::variant +# if defined(PYBIND11_CPP17) && __has_include(<variant>) +# include <variant> +# define PYBIND11_HAS_VARIANT 1 +# endif +#elif defined(_MSC_VER) && defined(PYBIND11_CPP17) +# include <optional> +# include <variant> +# define PYBIND11_HAS_OPTIONAL 1 +# define PYBIND11_HAS_VARIANT 1 #endif -NAMESPACE_BEGIN(pybind11) +NAMESPACE_BEGIN(PYBIND11_NAMESPACE) NAMESPACE_BEGIN(detail) +/// Extracts an const lvalue reference or rvalue reference for U based on the type of T (e.g. for +/// forwarding a container element). Typically used indirect via forwarded_type(), below. +template <typename T, typename U> +using forwarded_type = conditional_t< + std::is_lvalue_reference<T>::value, remove_reference_t<U> &, remove_reference_t<U> &&>; + +/// Forwards a value U as rvalue or lvalue according to whether T is rvalue or lvalue; typically +/// used for forwarding a container's elements. +template <typename T, typename U> +forwarded_type<T, U> forward_like(U &&u) { + return std::forward<detail::forwarded_type<T, U>>(std::forward<U>(u)); +} + template <typename Type, typename Key> struct set_caster { using type = Type; using key_conv = make_caster<Key>; @@ -50,19 +71,20 @@ template <typename Type, typename Key> struct set_caster { return false; auto s = reinterpret_borrow<pybind11::set>(src); value.clear(); - key_conv conv; for (auto entry : s) { + key_conv conv; if (!conv.load(entry, convert)) return false; - value.insert(cast_op<Key>(conv)); + value.insert(cast_op<Key &&>(std::move(conv))); } return true; } - static handle cast(const type &src, return_value_policy policy, handle parent) { + template <typename T> + static handle cast(T &&src, return_value_policy policy, handle parent) { pybind11::set s; - for (auto const &value: src) { - auto value_ = reinterpret_steal<object>(key_conv::cast(value, policy, parent)); + for (auto &&value : src) { + auto value_ = reinterpret_steal<object>(key_conv::cast(forward_like<T>(value), policy, parent)); if (!value_ || !s.add(value_)) return handle(); } @@ -80,23 +102,24 @@ template <typename Type, typename Key, typename Value> struct map_caster { if (!isinstance<dict>(src)) return false; auto d = reinterpret_borrow<dict>(src); - key_conv kconv; - value_conv vconv; value.clear(); for (auto it : d) { + key_conv kconv; + value_conv vconv; if (!kconv.load(it.first.ptr(), convert) || !vconv.load(it.second.ptr(), convert)) return false; - value.emplace(cast_op<Key>(kconv), cast_op<Value>(vconv)); + value.emplace(cast_op<Key &&>(std::move(kconv)), cast_op<Value &&>(std::move(vconv))); } return true; } - static handle cast(const Type &src, return_value_policy policy, handle parent) { + template <typename T> + static handle cast(T &&src, return_value_policy policy, handle parent) { dict d; - for (auto const &kv: src) { - auto key = reinterpret_steal<object>(key_conv::cast(kv.first, policy, parent)); - auto value = reinterpret_steal<object>(value_conv::cast(kv.second, policy, parent)); + for (auto &&kv : src) { + auto key = reinterpret_steal<object>(key_conv::cast(forward_like<T>(kv.first), policy, parent)); + auto value = reinterpret_steal<object>(value_conv::cast(forward_like<T>(kv.second), policy, parent)); if (!key || !value) return handle(); d[key] = value; @@ -114,13 +137,13 @@ template <typename Type, typename Value> struct list_caster { if (!isinstance<sequence>(src)) return false; auto s = reinterpret_borrow<sequence>(src); - value_conv conv; value.clear(); reserve_maybe(s, &value); for (auto it : s) { + value_conv conv; if (!conv.load(it, convert)) return false; - value.push_back(cast_op<Value>(conv)); + value.push_back(cast_op<Value &&>(std::move(conv))); } return true; } @@ -132,11 +155,12 @@ private: void reserve_maybe(sequence, void *) { } public: - static handle cast(const Type &src, return_value_policy policy, handle parent) { + template <typename T> + static handle cast(T &&src, return_value_policy policy, handle parent) { list l(src.size()); size_t index = 0; - for (auto const &value: src) { - auto value_ = reinterpret_steal<object>(value_conv::cast(value, policy, parent)); + for (auto &&value : src) { + auto value_ = reinterpret_steal<object>(value_conv::cast(forward_like<T>(value), policy, parent)); if (!value_) return handle(); PyList_SET_ITEM(l.ptr(), (ssize_t) index++, value_.release().ptr()); // steals a reference @@ -175,21 +199,22 @@ public: auto l = reinterpret_borrow<list>(src); if (!require_size(l.size())) return false; - value_conv conv; size_t ctr = 0; for (auto it : l) { + value_conv conv; if (!conv.load(it, convert)) return false; - value[ctr++] = cast_op<Value>(conv); + value[ctr++] = cast_op<Value &&>(std::move(conv)); } return true; } - static handle cast(const ArrayType &src, return_value_policy policy, handle parent) { + template <typename T> + static handle cast(T &&src, return_value_policy policy, handle parent) { list l(src.size()); size_t index = 0; - for (auto const &value: src) { - auto value_ = reinterpret_steal<object>(value_conv::cast(value, policy, parent)); + for (auto &&value : src) { + auto value_ = reinterpret_steal<object>(value_conv::cast(forward_like<T>(value), policy, parent)); if (!value_) return handle(); PyList_SET_ITEM(l.ptr(), (ssize_t) index++, value_.release().ptr()); // steals a reference @@ -222,24 +247,24 @@ template <typename Key, typename Value, typename Hash, typename Equal, typename template<typename T> struct optional_caster { using value_conv = make_caster<typename T::value_type>; - static handle cast(const T& src, return_value_policy policy, handle parent) { + template <typename T_> + static handle cast(T_ &&src, return_value_policy policy, handle parent) { if (!src) return none().inc_ref(); - return value_conv::cast(*src, policy, parent); + return value_conv::cast(*std::forward<T_>(src), policy, parent); } bool load(handle src, bool convert) { if (!src) { return false; } else if (src.is_none()) { - value = {}; // nullopt - return true; + return true; // default-constructed value is already empty } value_conv inner_caster; if (!inner_caster.load(src, convert)) return false; - value.emplace(cast_op<typename T::value_type>(inner_caster)); + value.emplace(cast_op<typename T::value_type &&>(std::move(inner_caster))); return true; } @@ -262,6 +287,74 @@ template<> struct type_caster<std::experimental::nullopt_t> : public void_caster<std::experimental::nullopt_t> {}; #endif +/// Visit a variant and cast any found type to Python +struct variant_caster_visitor { + return_value_policy policy; + handle parent; + + using result_type = handle; // required by boost::variant in C++11 + + template <typename T> + result_type operator()(T &&src) const { + return make_caster<T>::cast(std::forward<T>(src), policy, parent); + } +}; + +/// Helper class which abstracts away variant's `visit` function. `std::variant` and similar +/// `namespace::variant` types which provide a `namespace::visit()` function are handled here +/// automatically using argument-dependent lookup. Users can provide specializations for other +/// variant-like classes, e.g. `boost::variant` and `boost::apply_visitor`. +template <template<typename...> class Variant> +struct visit_helper { + template <typename... Args> + static auto call(Args &&...args) -> decltype(visit(std::forward<Args>(args)...)) { + return visit(std::forward<Args>(args)...); + } +}; + +/// Generic variant caster +template <typename Variant> struct variant_caster; + +template <template<typename...> class V, typename... Ts> +struct variant_caster<V<Ts...>> { + static_assert(sizeof...(Ts) > 0, "Variant must consist of at least one alternative."); + + template <typename U, typename... Us> + bool load_alternative(handle src, bool convert, type_list<U, Us...>) { + auto caster = make_caster<U>(); + if (caster.load(src, convert)) { + value = cast_op<U>(caster); + return true; + } + return load_alternative(src, convert, type_list<Us...>{}); + } + + bool load_alternative(handle, bool, type_list<>) { return false; } + + bool load(handle src, bool convert) { + // Do a first pass without conversions to improve constructor resolution. + // E.g. `py::int_(1).cast<variant<double, int>>()` needs to fill the `int` + // slot of the variant. Without two-pass loading `double` would be filled + // because it appears first and a conversion is possible. + if (convert && load_alternative(src, false, type_list<Ts...>{})) + return true; + return load_alternative(src, convert, type_list<Ts...>{}); + } + + template <typename Variant> + static handle cast(Variant &&src, return_value_policy policy, handle parent) { + return visit_helper<V>::call(variant_caster_visitor{policy, parent}, + std::forward<Variant>(src)); + } + + using Type = V<Ts...>; + PYBIND11_TYPE_CASTER(Type, _("Union[") + detail::concat(make_caster<Ts>::name()...) + _("]")); +}; + +#ifdef PYBIND11_HAS_VARIANT +template <typename... Ts> +struct type_caster<std::variant<Ts...>> : variant_caster<std::variant<Ts...>> { }; +#endif NAMESPACE_END(detail) inline std::ostream &operator<<(std::ostream &os, const handle &obj) { @@ -269,7 +362,7 @@ inline std::ostream &operator<<(std::ostream &os, const handle &obj) { return os; } -NAMESPACE_END(pybind11) +NAMESPACE_END(PYBIND11_NAMESPACE) #if defined(_MSC_VER) #pragma warning(pop) diff --git a/ext/pybind11/include/pybind11/stl_bind.h b/ext/pybind11/include/pybind11/stl_bind.h index 897188220..7ef687878 100644 --- a/ext/pybind11/include/pybind11/stl_bind.h +++ b/ext/pybind11/include/pybind11/stl_bind.h @@ -9,13 +9,13 @@ #pragma once -#include "common.h" +#include "detail/common.h" #include "operators.h" #include <algorithm> #include <sstream> -NAMESPACE_BEGIN(pybind11) +NAMESPACE_BEGIN(PYBIND11_NAMESPACE) NAMESPACE_BEGIN(detail) /* SFINAE helper class used by 'is_comparable */ @@ -66,10 +66,7 @@ template <typename, typename, typename... Args> void vector_if_insertion_operato template <typename, typename, typename... Args> void vector_modifiers(const Args &...) { } template<typename Vector, typename Class_> -void vector_if_copy_constructible(enable_if_t< - std::is_copy_constructible<Vector>::value && - std::is_copy_constructible<typename Vector::value_type>::value, Class_> &cl) { - +void vector_if_copy_constructible(enable_if_t<is_copy_constructible<Vector>::value, Class_> &cl) { cl.def(init<const Vector &>(), "Copy constructor"); } @@ -113,7 +110,7 @@ void vector_if_equal_operator(enable_if_t<is_comparable<Vector>::value, Class_> // (Technically, some of these (pop and __delitem__) don't actually require copyability, but it seems // silly to allow deletion but not insertion, so include them here too.) template <typename Vector, typename Class_> -void vector_modifiers(enable_if_t<std::is_copy_constructible<typename Vector::value_type>::value, Class_> &cl) { +void vector_modifiers(enable_if_t<is_copy_constructible<typename Vector::value_type>::value, Class_> &cl) { using T = typename Vector::value_type; using SizeType = typename Vector::size_type; using DiffType = typename Vector::difference_type; @@ -123,21 +120,16 @@ void vector_modifiers(enable_if_t<std::is_copy_constructible<typename Vector::va arg("x"), "Add an item to the end of the list"); - cl.def("__init__", [](Vector &v, iterable it) { - new (&v) Vector(); - try { - v.reserve(len(it)); - for (handle h : it) - v.push_back(h.cast<T>()); - } catch (...) { - v.~Vector(); - throw; - } - }); + cl.def(init([](iterable it) { + auto v = std::unique_ptr<Vector>(new Vector()); + v->reserve(len(it)); + for (handle h : it) + v->push_back(h.cast<T>()); + return v.release(); + })); cl.def("extend", [](Vector &v, const Vector &src) { - v.reserve(v.size() + src.size()); v.insert(v.end(), src.begin(), src.end()); }, arg("L"), @@ -146,6 +138,8 @@ void vector_modifiers(enable_if_t<std::is_copy_constructible<typename Vector::va cl.def("insert", [](Vector &v, SizeType i, const T &x) { + if (i > v.size()) + throw index_error(); v.insert(v.begin() + (DiffType) i, x); }, arg("i") , arg("x"), @@ -345,23 +339,25 @@ vector_buffer(Class_& cl) { format_descriptor<T>::format(); cl.def_buffer([](Vector& v) -> buffer_info { - return buffer_info(v.data(), sizeof(T), format_descriptor<T>::format(), 1, {v.size()}, {sizeof(T)}); + return buffer_info(v.data(), static_cast<ssize_t>(sizeof(T)), format_descriptor<T>::format(), 1, {v.size()}, {sizeof(T)}); }); - cl.def("__init__", [](Vector& vec, buffer buf) { + cl.def(init([](buffer buf) { auto info = buf.request(); - if (info.ndim != 1 || info.strides[0] <= 0 || info.strides[0] % sizeof(T)) + if (info.ndim != 1 || info.strides[0] % static_cast<ssize_t>(sizeof(T))) throw type_error("Only valid 1D buffers can be copied to a vector"); - if (!detail::compare_buffer_info<T>::compare(info) || sizeof(T) != info.itemsize) + if (!detail::compare_buffer_info<T>::compare(info) || (ssize_t) sizeof(T) != info.itemsize) throw type_error("Format mismatch (Python: " + info.format + " C++: " + format_descriptor<T>::format() + ")"); - new (&vec) Vector(); - vec.reserve(info.shape[0]); + + auto vec = std::unique_ptr<Vector>(new Vector()); + vec->reserve((size_t) info.shape[0]); T *p = static_cast<T*>(info.ptr); - auto step = info.strides[0] / sizeof(T); + ssize_t step = info.strides[0] / static_cast<ssize_t>(sizeof(T)); T *end = p + info.shape[0] * step; - for (; p < end; p += step) - vec.push_back(*p); - }); + for (; p != end; p += step) + vec->push_back(*p); + return vec.release(); + })); return; } @@ -375,10 +371,16 @@ NAMESPACE_END(detail) // std::vector // template <typename Vector, typename holder_type = std::unique_ptr<Vector>, typename... Args> -class_<Vector, holder_type> bind_vector(module &m, std::string const &name, Args&&... args) { +class_<Vector, holder_type> bind_vector(handle scope, std::string const &name, Args&&... args) { using Class_ = class_<Vector, holder_type>; - Class_ cl(m, name.c_str(), std::forward<Args>(args)...); + // If the value_type is unregistered (e.g. a converting type) or is itself registered + // module-local then make the vector binding module-local as well: + using vtype = typename Vector::value_type; + auto vtype_info = detail::get_type_info(typeid(vtype)); + bool local = !vtype_info || vtype_info->module_local; + + Class_ cl(scope, name.c_str(), pybind11::module_local(local), std::forward<Args>(args)...); // Declare the buffer interface if a buffer_protocol() is passed in detail::vector_buffer<Vector, Class_, Args...>(cl); @@ -486,7 +488,7 @@ void map_assignment(enable_if_t<std::is_copy_assignable<typename Map::mapped_typ template<typename Map, typename Class_> void map_assignment(enable_if_t< !std::is_copy_assignable<typename Map::mapped_type>::value && - std::is_copy_constructible<typename Map::mapped_type>::value, + is_copy_constructible<typename Map::mapped_type>::value, Class_> &cl) { using KeyType = typename Map::key_type; using MappedType = typename Map::mapped_type; @@ -530,12 +532,22 @@ template <typename Map, typename Class_> auto map_if_insertion_operator(Class_ & NAMESPACE_END(detail) template <typename Map, typename holder_type = std::unique_ptr<Map>, typename... Args> -class_<Map, holder_type> bind_map(module &m, const std::string &name, Args&&... args) { +class_<Map, holder_type> bind_map(handle scope, const std::string &name, Args&&... args) { using KeyType = typename Map::key_type; using MappedType = typename Map::mapped_type; using Class_ = class_<Map, holder_type>; - Class_ cl(m, name.c_str(), std::forward<Args>(args)...); + // If either type is a non-module-local bound type then make the map binding non-local as well; + // otherwise (e.g. both types are either module-local or converting) the map will be + // module-local. + auto tinfo = detail::get_type_info(typeid(MappedType)); + bool local = !tinfo || tinfo->module_local; + if (local) { + tinfo = detail::get_type_info(typeid(KeyType)); + local = !tinfo || tinfo->module_local; + } + + Class_ cl(scope, name.c_str(), pybind11::module_local(local), std::forward<Args>(args)...); cl.def(init<>()); @@ -584,4 +596,4 @@ class_<Map, holder_type> bind_map(module &m, const std::string &name, Args&&... return cl; } -NAMESPACE_END(pybind11) +NAMESPACE_END(PYBIND11_NAMESPACE) |