summaryrefslogtreecommitdiff
path: root/ext/pybind11/include
diff options
context:
space:
mode:
Diffstat (limited to 'ext/pybind11/include')
-rw-r--r--ext/pybind11/include/pybind11/attr.h121
-rw-r--r--ext/pybind11/include/pybind11/buffer_info.h108
-rw-r--r--ext/pybind11/include/pybind11/cast.h1257
-rw-r--r--ext/pybind11/include/pybind11/chrono.h4
-rw-r--r--ext/pybind11/include/pybind11/common.h721
-rw-r--r--ext/pybind11/include/pybind11/complex.h17
-rw-r--r--ext/pybind11/include/pybind11/detail/class.h (renamed from ext/pybind11/include/pybind11/class_support.h)322
-rw-r--r--ext/pybind11/include/pybind11/detail/common.h800
-rw-r--r--ext/pybind11/include/pybind11/detail/descr.h (renamed from ext/pybind11/include/pybind11/descr.h)20
-rw-r--r--ext/pybind11/include/pybind11/detail/init.h325
-rw-r--r--ext/pybind11/include/pybind11/detail/internals.h247
-rw-r--r--ext/pybind11/include/pybind11/detail/typeid.h (renamed from ext/pybind11/include/pybind11/typeid.h)6
-rw-r--r--ext/pybind11/include/pybind11/eigen.h117
-rw-r--r--ext/pybind11/include/pybind11/embed.h194
-rw-r--r--ext/pybind11/include/pybind11/eval.h37
-rw-r--r--ext/pybind11/include/pybind11/functional.h28
-rw-r--r--ext/pybind11/include/pybind11/iostream.h200
-rw-r--r--ext/pybind11/include/pybind11/numpy.h635
-rw-r--r--ext/pybind11/include/pybind11/operators.h52
-rw-r--r--ext/pybind11/include/pybind11/options.h6
-rw-r--r--ext/pybind11/include/pybind11/pybind11.h562
-rw-r--r--ext/pybind11/include/pybind11/pytypes.h196
-rw-r--r--ext/pybind11/include/pybind11/stl.h157
-rw-r--r--ext/pybind11/include/pybind11/stl_bind.h82
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 &registered_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 &registered_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 *> &registered_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> &params,
+ 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> &params,
+ 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)