diff options
author | Andreas Sandberg <andreas.sandberg@arm.com> | 2017-02-27 13:17:51 +0000 |
---|---|---|
committer | Andreas Sandberg <andreas.sandberg@arm.com> | 2017-05-02 12:37:32 +0000 |
commit | c79706ff4ce591df2151db5504d3c224f3c9965f (patch) | |
tree | b56cd2bfe704a40575a71075e78194a4c516c98d /ext/pybind11/include | |
parent | 359cb08623324b62d7c34973ae54d5bc7f23f9fd (diff) | |
download | gem5-c79706ff4ce591df2151db5504d3c224f3c9965f.tar.xz |
ext: Add pybind rev f4b81b3
Change-Id: I52e4fc9ebf2f59da57d8cf8f3e37cc79598c2f5f
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Andreas Hansson <andreas.hansson@arm.com>
Reviewed-by: Curtis Dunham <curtis.dunham@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2229
Reviewed-by: Tony Gutierrez <anthony.gutierrez@amd.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Reviewed-by: Pierre-Yves PĂ©neau <pierre-yves.peneau@lirmm.fr>
Diffstat (limited to 'ext/pybind11/include')
-rw-r--r-- | ext/pybind11/include/pybind11/attr.h | 362 | ||||
-rw-r--r-- | ext/pybind11/include/pybind11/cast.h | 1468 | ||||
-rw-r--r-- | ext/pybind11/include/pybind11/chrono.h | 160 | ||||
-rw-r--r-- | ext/pybind11/include/pybind11/common.h | 595 | ||||
-rw-r--r-- | ext/pybind11/include/pybind11/complex.h | 47 | ||||
-rw-r--r-- | ext/pybind11/include/pybind11/descr.h | 183 | ||||
-rw-r--r-- | ext/pybind11/include/pybind11/eigen.h | 239 | ||||
-rw-r--r-- | ext/pybind11/include/pybind11/eval.h | 105 | ||||
-rw-r--r-- | ext/pybind11/include/pybind11/functional.h | 79 | ||||
-rw-r--r-- | ext/pybind11/include/pybind11/numpy.h | 1169 | ||||
-rw-r--r-- | ext/pybind11/include/pybind11/operators.h | 154 | ||||
-rw-r--r-- | ext/pybind11/include/pybind11/options.h | 65 | ||||
-rw-r--r-- | ext/pybind11/include/pybind11/pybind11.h | 1735 | ||||
-rw-r--r-- | ext/pybind11/include/pybind11/pytypes.h | 920 | ||||
-rw-r--r-- | ext/pybind11/include/pybind11/stl.h | 276 | ||||
-rw-r--r-- | ext/pybind11/include/pybind11/stl_bind.h | 541 | ||||
-rw-r--r-- | ext/pybind11/include/pybind11/typeid.h | 53 |
17 files changed, 8151 insertions, 0 deletions
diff --git a/ext/pybind11/include/pybind11/attr.h b/ext/pybind11/include/pybind11/attr.h new file mode 100644 index 000000000..448612c52 --- /dev/null +++ b/ext/pybind11/include/pybind11/attr.h @@ -0,0 +1,362 @@ +/* + pybind11/pybind11.h: Infrastructure for processing custom + type and function attributes + + 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 "cast.h" + +NAMESPACE_BEGIN(pybind11) + +/// Annotation for methods +struct is_method { handle class_; is_method(const handle &c) : class_(c) { } }; + +/// Annotation for operators +struct is_operator { }; + +/// Annotation for parent scope +struct scope { handle value; scope(const handle &s) : value(s) { } }; + +/// Annotation for documentation +struct doc { const char *value; doc(const char *value) : value(value) { } }; + +/// Annotation for function names +struct name { const char *value; name(const char *value) : value(value) { } }; + +/// Annotation indicating that a function is an overload associated with a given "sibling" +struct sibling { handle value; sibling(const handle &value) : value(value.ptr()) { } }; + +/// Annotation indicating that a class derives from another given type +template <typename T> struct base { + PYBIND11_DEPRECATED("base<T>() was deprecated in favor of specifying 'T' as a template argument to class_") + base() { } +}; + +/// Keep patient alive while nurse lives +template <int Nurse, int Patient> struct keep_alive { }; + +/// Annotation indicating that a class is involved in a multiple inheritance relationship +struct multiple_inheritance { }; + +/// Annotation which enables dynamic attributes, i.e. adds `__dict__` to a class +struct dynamic_attr { }; + +/// Annotation to mark enums as an arithmetic type +struct arithmetic { }; + +NAMESPACE_BEGIN(detail) +/* Forward declarations */ +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(int Nurse, int Patient, handle args, handle ret); + +/// Internal data structure which holds metadata about a keyword argument +struct argument_record { + const char *name; ///< Argument name + const char *descr; ///< Human-readable version of the argument value + handle value; ///< Associated Python object + + argument_record(const char *name, const char *descr, handle value) + : name(name), descr(descr), value(value) { } +}; + +/// 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) { } + + /// Function name + char *name = nullptr; /* why no C++ strings? They generate heavier code.. */ + + // User-specified documentation string + char *doc = nullptr; + + /// Human-readable version of the function signature + char *signature = nullptr; + + /// List of registered keyword arguments + std::vector<argument_record> args; + + /// Pointer to lambda function which converts arguments and performs the actual call + handle (*impl) (function_record *, handle, handle, handle) = nullptr; + + /// Storage for the wrapped function pointer and captured data, if any + void *data[3] = { }; + + /// Pointer to custom destructor for 'data' (if needed) + void (*free_data) (function_record *ptr) = nullptr; + + /// Return value policy associated with this function + return_value_policy policy = return_value_policy::automatic; + + /// True if name == '__init__' + bool is_constructor : 1; + + /// True if this is a stateless function pointer + bool is_stateless : 1; + + /// True if this is an operator (__add__), etc. + bool is_operator : 1; + + /// True if the function has a '*args' argument + bool has_args : 1; + + /// True if the function has a '**kwargs' argument + bool has_kwargs : 1; + + /// True if this is a method + bool is_method : 1; + + /// Number of arguments + uint16_t nargs; + + /// Python method object + PyMethodDef *def = nullptr; + + /// Python handle to the parent scope (a class or a module) + handle scope; + + /// Python handle to the sibling function representing an overload chain + handle sibling; + + /// Pointer to next overload + function_record *next = nullptr; +}; + +/// Special data structure which (temporarily) holds metadata about a bound class +struct type_record { + PYBIND11_NOINLINE type_record() { } + + /// Handle to the parent scope + handle scope; + + /// Name of the class + const char *name = nullptr; + + // Pointer to RTTI type_info data structure + const std::type_info *type = nullptr; + + /// How large is the underlying C++ type? + size_t type_size = 0; + + /// How large is pybind11::instance<type>? + size_t instance_size = 0; + + /// Function pointer to class_<..>::init_holder + void (*init_holder)(PyObject *, const void *) = nullptr; + + /// Function pointer to class_<..>::dealloc + void (*dealloc)(PyObject *) = nullptr; + + /// List of base classes of the newly created type + list bases; + + /// Optional docstring + const char *doc = nullptr; + + /// Multiple inheritance marker + bool multiple_inheritance = false; + + /// Does the class manage a __dict__? + bool dynamic_attr = false; + + 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()); + detail::clean_type_id(tname); + pybind11_fail("generic_type: type \"" + std::string(name) + + "\" referenced unknown base type \"" + tname + "\""); + } + + bases.append((PyObject *) base_info->type); + + if (base_info->type->tp_dictoffset != 0) + dynamic_attr = true; + + if (caster) + base_info->implicit_casts.push_back(std::make_pair(type, caster)); + } +}; + +/** + * Partial template specializations to process custom attributes provided to + * cpp_function_ and class_. These are either used to initialize the respective + * fields in the type_record and function_record data structures or executed at + * runtime to deal with custom call policies (e.g. keep_alive). + */ +template <typename T, typename SFINAE = void> struct process_attribute; + +template <typename T> struct process_attribute_default { + /// Default implementation: do nothing + static void init(const T &, function_record *) { } + static void init(const T &, type_record *) { } + static void precall(handle) { } + static void postcall(handle, handle) { } +}; + +/// Process an attribute specifying the function's name +template <> struct process_attribute<name> : process_attribute_default<name> { + static void init(const name &n, function_record *r) { r->name = const_cast<char *>(n.value); } +}; + +/// Process an attribute specifying the function's docstring +template <> struct process_attribute<doc> : process_attribute_default<doc> { + static void init(const doc &n, function_record *r) { r->doc = const_cast<char *>(n.value); } +}; + +/// Process an attribute specifying the function's docstring (provided as a C-style string) +template <> struct process_attribute<const char *> : process_attribute_default<const char *> { + static void init(const char *d, function_record *r) { r->doc = const_cast<char *>(d); } + static void init(const char *d, type_record *r) { r->doc = const_cast<char *>(d); } +}; +template <> struct process_attribute<char *> : process_attribute<const char *> { }; + +/// Process an attribute indicating the function's return value policy +template <> struct process_attribute<return_value_policy> : process_attribute_default<return_value_policy> { + static void init(const return_value_policy &p, function_record *r) { r->policy = p; } +}; + +/// Process an attribute which indicates that this is an overloaded function associated with a given sibling +template <> struct process_attribute<sibling> : process_attribute_default<sibling> { + static void init(const sibling &s, function_record *r) { r->sibling = s.value; } +}; + +/// Process an attribute which indicates that this function is a method +template <> struct process_attribute<is_method> : process_attribute_default<is_method> { + static void init(const is_method &s, function_record *r) { r->is_method = true; r->scope = s.class_; } +}; + +/// Process an attribute which indicates the parent scope of a method +template <> struct process_attribute<scope> : process_attribute_default<scope> { + static void init(const scope &s, function_record *r) { r->scope = s.value; } +}; + +/// Process an attribute which indicates that this function is an operator +template <> struct process_attribute<is_operator> : process_attribute_default<is_operator> { + static void init(const is_operator &, function_record *r) { r->is_operator = 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()); + r->args.emplace_back(a.name, nullptr, handle()); + } +}; + +/// Process a keyword argument attribute (*with* a default value) +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, handle()); + + if (!a.value) { +#if !defined(NDEBUG) + auto descr = "'" + std::string(a.name) + ": " + a.type + "'"; + if (r->is_method) { + if (r->name) + descr += " in method '" + (std::string) str(r->scope) + "." + (std::string) r->name + "'"; + else + descr += " in method of '" + (std::string) str(r->scope) + "'"; + } else if (r->name) { + descr += " in function named '" + (std::string) r->name + "'"; + } + pybind11_fail("arg(): could not convert default keyword argument " + + descr + " into a Python object (type not registered yet?)"); +#else + pybind11_fail("arg(): could not convert default keyword argument " + "into a Python object (type not registered yet?). " + "Compile in debug mode for more information."); +#endif + } + r->args.emplace_back(a.name, a.descr, a.value.inc_ref()); + } +}; + +/// Process a parent class attribute +template <typename T> +struct process_attribute<T, enable_if_t<is_pyobject<T>::value>> : process_attribute_default<handle> { + static void init(const handle &h, type_record *r) { r->bases.append(h); } +}; + +/// 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); } +}; + +/// Process a multiple inheritance attribute +template <> +struct process_attribute<multiple_inheritance> : process_attribute_default<multiple_inheritance> { + static void init(const multiple_inheritance &, type_record *r) { r->multiple_inheritance = true; } +}; + +template <> +struct process_attribute<dynamic_attr> : process_attribute_default<dynamic_attr> { + static void init(const dynamic_attr &, type_record *r) { r->dynamic_attr = true; } +}; + + +/// Process an 'arithmetic' attribute for enums (does nothing here) +template <> +struct process_attribute<arithmetic> : process_attribute_default<arithmetic> {}; + +/*** + * 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 + */ +template <int Nurse, int Patient> struct process_attribute<keep_alive<Nurse, Patient>> : public process_attribute_default<keep_alive<Nurse, Patient>> { + template <int N = Nurse, int P = Patient, enable_if_t<N != 0 && P != 0, int> = 0> + static void precall(handle args) { keep_alive_impl(Nurse, Patient, args, handle()); } + template <int N = Nurse, int P = Patient, enable_if_t<N != 0 && P != 0, int> = 0> + static void postcall(handle, handle) { } + template <int N = Nurse, int P = Patient, enable_if_t<N == 0 || P == 0, int> = 0> + static void precall(handle) { } + template <int N = Nurse, int P = Patient, enable_if_t<N == 0 || P == 0, int> = 0> + static void postcall(handle args, handle ret) { keep_alive_impl(Nurse, Patient, args, ret); } +}; + +/// Recursively iterate over variadic template arguments +template <typename... Args> struct process_attributes { + static void init(const Args&... args, function_record *r) { + int unused[] = { 0, (process_attribute<typename std::decay<Args>::type>::init(args, r), 0) ... }; + ignore_unused(unused); + } + static void init(const Args&... args, type_record *r) { + int unused[] = { 0, (process_attribute<typename std::decay<Args>::type>::init(args, r), 0) ... }; + ignore_unused(unused); + } + static void precall(handle fn_args) { + int unused[] = { 0, (process_attribute<typename std::decay<Args>::type>::precall(fn_args), 0) ... }; + ignore_unused(unused); + } + static void postcall(handle fn_args, handle fn_ret) { + int unused[] = { 0, (process_attribute<typename std::decay<Args>::type>::postcall(fn_args, fn_ret), 0) ... }; + ignore_unused(unused); + } +}; + +/// Check the number of named arguments at compile time +template <typename... Extra, + size_t named = constexpr_sum(std::is_base_of<arg, Extra>::value...), + size_t self = constexpr_sum(std::is_same<is_method, Extra>::value...)> +constexpr bool expected_num_args(size_t nargs) { + return named == 0 || (self + named) == nargs; +} + +NAMESPACE_END(detail) +NAMESPACE_END(pybind11) diff --git a/ext/pybind11/include/pybind11/cast.h b/ext/pybind11/include/pybind11/cast.h new file mode 100644 index 000000000..535516b37 --- /dev/null +++ b/ext/pybind11/include/pybind11/cast.h @@ -0,0 +1,1468 @@ +/* + pybind11/cast.h: Partial template specializations to cast between + C++ and Python types + + 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 "pytypes.h" +#include "typeid.h" +#include "descr.h" +#include <array> +#include <limits> + +NAMESPACE_BEGIN(pybind11) +NAMESPACE_BEGIN(detail) + +/// Additional type information which does not fit into the PyTypeObject +struct type_info { + PyTypeObject *type; + size_t type_size; + void (*init_holder)(PyObject *, const void *); + 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; +}; + +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; + } + } + ); + } + return *internals_ptr; +} + +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); +} + +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; + + auto it = types.find(std::type_index(tp)); + if (it != types.end()) + return (detail::type_info *) it->second; + if (throw_if_missing) { + std::string tname = tp.name(); + detail::clean_type_id(tname); + pybind11_fail("pybind11::detail::get_type_info: unable to find type info for \"" + tname + "\""); + } + return nullptr; +} + +PYBIND11_NOINLINE inline handle get_type_handle(const std::type_info &tp, bool throw_if_missing) { + detail::type_info *type_info = get_type_info(tp, throw_if_missing); + return handle(type_info ? ((PyObject *) type_info->type) : nullptr); +} + +PYBIND11_NOINLINE inline bool isinstance_generic(handle obj, const std::type_info &tp) { + const auto type = detail::get_type_handle(tp, false); + if (!type) + return false; + + const auto result = PyObject_IsInstance(obj.ptr(), type.ptr()); + if (result == -1) + throw error_already_set(); + return result != 0; +} + +PYBIND11_NOINLINE inline std::string error_string() { + if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_RuntimeError, "Unknown internal error occurred"); + return "Unknown internal error occurred"; + } + + error_scope scope; // Preserve error state + + std::string errorString; + if (scope.type) { + errorString += handle(scope.type).attr("__name__").cast<std::string>(); + errorString += ": "; + } + if (scope.value) + errorString += (std::string) str(scope.value); + + PyErr_NormalizeException(&scope.type, &scope.value, &scope.trace); + +#if PY_MAJOR_VERSION >= 3 + if (scope.trace != nullptr) + PyException_SetTraceback(scope.value, scope.trace); +#endif + + if (scope.trace) { + PyTracebackObject *trace = (PyTracebackObject *) scope.trace; + + /* Get the deepest trace possible */ + while (trace->tb_next) + trace = trace->tb_next; + + PyFrameObject *frame = trace->tb_frame; + errorString += "\n\nAt:\n"; + while (frame) { + int lineno = PyFrame_GetLineNumber(frame); + errorString += + " " + handle(frame->f_code->co_filename).cast<std::string>() + + "(" + std::to_string(lineno) + "): " + + handle(frame->f_code->co_name).cast<std::string>() + "\n"; + frame = frame->f_back; + } + trace = trace->tb_next; + } + + return errorString; +} + +PYBIND11_NOINLINE inline handle get_object_handle(const void *ptr, const detail::type_info *type ) { + 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); + } + return handle(); +} + +inline PyThreadState *get_thread_state_unchecked() { +#if PY_VERSION_HEX < 0x03000000 + return _PyThreadState_Current; +#elif PY_VERSION_HEX < 0x03050000 + return (PyThreadState*) _Py_atomic_load_relaxed(&_PyThreadState_Current); +#elif PY_VERSION_HEX < 0x03050200 + return (PyThreadState*) _PyThreadState_Current.value; +#else + return _PyThreadState_UncheckedGet(); +#endif +} + +// Forward declaration +inline void keep_alive_impl(handle nurse, handle patient); + +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; + } + + 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; + } + + /* 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(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; + } + + 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, + 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()); + return handle(); + } + + auto tinfo = (const detail::type_info *) it->second; + + auto it_instances = 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(); + } + + auto inst = reinterpret_steal<object>(PyType_GenericAlloc(tinfo->type, 0)); + + auto wrapper = (instance<void> *) inst.ptr(); + + wrapper->value = nullptr; + wrapper->owned = false; + + switch (policy) { + case return_value_policy::automatic: + case return_value_policy::take_ownership: + wrapper->value = src; + wrapper->owned = true; + break; + + case return_value_policy::automatic_reference: + case return_value_policy::reference: + wrapper->value = src; + wrapper->owned = false; + break; + + case return_value_policy::copy: + if (copy_constructor) + wrapper->value = copy_constructor(src); + else + throw cast_error("return_value_policy = copy, but the " + "object is non-copyable!"); + wrapper->owned = true; + break; + + case return_value_policy::move: + if (move_constructor) + wrapper->value = move_constructor(src); + else if (copy_constructor) + wrapper->value = copy_constructor(src); + else + throw cast_error("return_value_policy = move, but the " + "object is neither movable nor copyable!"); + wrapper->owned = true; + break; + + case return_value_policy::reference_internal: + wrapper->value = src; + wrapper->owned = false; + detail::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()); + + return inst.release(); + } + +protected: + const type_info *typeinfo = nullptr; + void *value = nullptr; + object temp; +}; + +/* Determine suitable casting operator */ +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; + +// 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. +template <typename T, typename SFINAE = void> struct is_copy_constructible : std::is_copy_constructible<T> {}; + +// 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> {}; + +/// Generic type caster for objects stored on the heap +template <typename type> class type_caster_base : public type_caster_generic { + using itype = intrinsic_t<type>; +public: + static PYBIND11_DESCR name() { return type_descr(_<type>()); } + + type_caster_base() : type_caster_base(typeid(type)) { } + explicit type_caster_base(const std::type_info &info) : type_caster_generic(info) { } + + static handle cast(const itype &src, return_value_policy policy, handle parent) { + if (policy == return_value_policy::automatic || policy == return_value_policy::automatic_reference) + policy = return_value_policy::copy; + return cast(&src, policy, parent); + } + + static handle cast(itype &&src, return_value_policy, handle parent) { + return cast(&src, return_value_policy::move, parent); + } + + static handle cast(const itype *src, return_value_policy policy, handle parent) { + return type_caster_generic::cast( + src, policy, parent, src ? &typeid(*src) : nullptr, &typeid(type), + make_copy_constructor(src), make_move_constructor(src)); + } + + template <typename T> using cast_op_type = pybind11::detail::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) + /* 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(*((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 + + static Constructor make_copy_constructor(...) { return nullptr; } + static Constructor make_move_constructor(...) { return nullptr; } +}; + +template <typename type, typename SFINAE = void> class type_caster : public type_caster_base<type> { }; +template <typename type> using make_caster = type_caster<intrinsic_t<type>>; + +// Shortcut for calling a caster's `cast_op_type` cast operator for casting a type_caster to a T +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 type> class type_caster<std::reference_wrapper<type>> : public type_caster_base<type> { +public: + 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); + } + template <typename T> using cast_op_type = std::reference_wrapper<type>; + operator std::reference_wrapper<type>() { return std::ref(*((type *) this->value)); } +}; + +#define PYBIND11_TYPE_CASTER(type, py_name) \ + protected: \ + type value; \ + public: \ + static PYBIND11_DESCR name() { return type_descr(py_name); } \ + static handle cast(const type *src, return_value_policy policy, handle parent) { \ + 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> + + +template <typename T> +struct type_caster<T, enable_if_t<std::is_arithmetic<T>::value>> { + typedef typename std::conditional<sizeof(T) <= sizeof(long), long, long long>::type _py_type_0; + typedef typename std::conditional<std::is_signed<T>::value, _py_type_0, typename std::make_unsigned<_py_type_0>::type>::type _py_type_1; + typedef typename std::conditional<std::is_floating_point<T>::value, double, _py_type_1>::type py_type; +public: + + bool load(handle src, bool) { + py_type py_value; + + if (!src) { + return false; + } if (std::is_floating_point<T>::value) { + py_value = (py_type) PyFloat_AsDouble(src.ptr()); + } 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()); + } + + 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); +#else + bool type_error = PyErr_ExceptionMatches(PyExc_TypeError); +#endif + PyErr_Clear(); + if (type_error && PyNumber_Check(src.ptr())) { + auto tmp = reinterpret_borrow<object>(std::is_floating_point<T>::value + ? PyNumber_Float(src.ptr()) + : PyNumber_Long(src.ptr())); + PyErr_Clear(); + return load(tmp, false); + } + return false; + } + + value = (T) py_value; + return true; + } + + static handle cast(T src, return_value_policy /* policy */, handle /* parent */) { + if (std::is_floating_point<T>::value) { + return PyFloat_FromDouble((double) src); + } else if (sizeof(T) <= sizeof(long)) { + if (std::is_signed<T>::value) + return PyLong_FromLong((long) src); + else + return PyLong_FromUnsignedLong((unsigned long) src); + } else { + if (std::is_signed<T>::value) + return PyLong_FromLongLong((long long) src); + else + return PyLong_FromUnsignedLongLong((unsigned long long) src); + } + } + + PYBIND11_TYPE_CASTER(T, _<std::is_integral<T>::value>("int", "float")); +}; + +template<typename T> struct void_caster { +public: + bool load(handle, bool) { return false; } + static handle cast(T, return_value_policy /* policy */, handle /* parent */) { + return none().inc_ref(); + } + PYBIND11_TYPE_CASTER(T, _("None")); +}; + +template <> class type_caster<void_type> : public void_caster<void_type> {}; + +template <> class type_caster<void> : public type_caster<void_type> { +public: + using type_caster<void_type>::cast; + + bool load(handle h, bool) { + if (!h) { + return false; + } else if (h.is_none()) { + value = nullptr; + return true; + } + + /* Check if this is a capsule */ + if (isinstance<capsule>(h)) { + value = reinterpret_borrow<capsule>(h); + return true; + } + + /* Check if this is a C++ type */ + if (get_type_info((PyTypeObject *) h.get_type().ptr())) { + value = ((instance<void> *) h.ptr())->value; + return true; + } + + /* Fail */ + return false; + } + + static handle cast(const void *ptr, return_value_policy /* policy */, handle /* parent */) { + if (ptr) + return capsule(ptr).release(); + else + return none().inc_ref(); + } + + template <typename T> using cast_op_type = void*&; + operator void *&() { return value; } + static PYBIND11_DESCR name() { return type_descr(_("capsule")); } +private: + void *value = nullptr; +}; + +template <> class type_caster<std::nullptr_t> : public type_caster<void_type> { }; + +template <> class type_caster<bool> { +public: + bool load(handle src, bool) { + 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; + } + static handle cast(bool src, return_value_policy /* policy */, handle /* parent */) { + return handle(src ? Py_True : Py_False).inc_ref(); + } + PYBIND11_TYPE_CASTER(bool, _("bool")); +}; + +template <> class type_caster<std::string> { +public: + bool load(handle src, bool) { + object temp; + handle load_src = src; + if (!src) { + return false; + } else if (PyUnicode_Check(load_src.ptr())) { + temp = reinterpret_steal<object>(PyUnicode_AsUTF8String(load_src.ptr())); + if (!temp) { PyErr_Clear(); return false; } // UnicodeEncodeError + load_src = temp; + } + char *buffer; + ssize_t length; + int err = PYBIND11_BYTES_AS_STRING_AND_SIZE(load_src.ptr(), &buffer, &length); + if (err == -1) { PyErr_Clear(); return false; } // TypeError + value = std::string(buffer, (size_t) length); + success = true; + return true; + } + + static handle cast(const std::string &src, return_value_policy /* policy */, handle /* parent */) { + return PyUnicode_FromStringAndSize(src.c_str(), (ssize_t) src.length()); + } + + PYBIND11_TYPE_CASTER(std::string, _(PYBIND11_STRING_NAME)); +protected: + bool success = false; +}; + +template <typename type, typename deleter> class type_caster<std::unique_ptr<type, deleter>> { +public: + static handle cast(std::unique_ptr<type, deleter> &&src, return_value_policy policy, handle parent) { + handle result = type_caster_base<type>::cast(src.get(), policy, parent); + if (result) + src.release(); + return result; + } + static PYBIND11_DESCR name() { return type_caster_base<type>::name(); } +}; + +template <> class type_caster<std::wstring> { +public: + bool load(handle src, bool) { + object temp; + handle load_src = src; + if (!src) { + return false; + } else if (!PyUnicode_Check(load_src.ptr())) { + temp = reinterpret_steal<object>(PyUnicode_FromObject(load_src.ptr())); + if (!temp) { PyErr_Clear(); return false; } + load_src = temp; + } + wchar_t *buffer = nullptr; + ssize_t length = -1; +#if PY_MAJOR_VERSION >= 3 + buffer = PyUnicode_AsWideCharString(load_src.ptr(), &length); +#else + temp = reinterpret_steal<object>( + sizeof(wchar_t) == sizeof(short) + ? PyUnicode_AsUTF16String(load_src.ptr()) + : PyUnicode_AsUTF32String(load_src.ptr())); + if (temp) { + int err = PYBIND11_BYTES_AS_STRING_AND_SIZE(temp.ptr(), (char **) &buffer, &length); + if (err == -1) { buffer = nullptr; } // TypeError + length = length / (ssize_t) sizeof(wchar_t) - 1; ++buffer; // Skip BOM + } +#endif + if (!buffer) { PyErr_Clear(); return false; } + value = std::wstring(buffer, (size_t) length); + success = true; + return true; + } + + static handle cast(const std::wstring &src, return_value_policy /* policy */, handle /* parent */) { + return PyUnicode_FromWideChar(src.c_str(), (ssize_t) src.length()); + } + + PYBIND11_TYPE_CASTER(std::wstring, _(PYBIND11_STRING_NAME)); +protected: + bool success = false; +}; + +template <> class type_caster<char> : public type_caster<std::string> { +public: + bool load(handle src, bool convert) { + if (src.is_none()) return true; + return type_caster<std::string>::load(src, convert); + } + + static handle cast(const char *src, return_value_policy /* policy */, handle /* parent */) { + if (src == nullptr) return none().inc_ref(); + return PyUnicode_FromString(src); + } + + static handle cast(char src, return_value_policy /* policy */, handle /* parent */) { + char str[2] = { src, '\0' }; + return PyUnicode_DecodeLatin1(str, 1, nullptr); + } + + operator char*() { return success ? (char *) value.c_str() : nullptr; } + operator char&() { return value[0]; } + + static PYBIND11_DESCR name() { return type_descr(_(PYBIND11_STRING_NAME)); } +}; + +template <> class type_caster<wchar_t> : public type_caster<std::wstring> { +public: + bool load(handle src, bool convert) { + if (src.is_none()) return true; + return type_caster<std::wstring>::load(src, convert); + } + + static handle cast(const wchar_t *src, return_value_policy /* policy */, handle /* parent */) { + if (src == nullptr) return none().inc_ref(); + return PyUnicode_FromWideChar(src, (ssize_t) wcslen(src)); + } + + static handle cast(wchar_t src, return_value_policy /* policy */, handle /* parent */) { + wchar_t wstr[2] = { src, L'\0' }; + return PyUnicode_FromWideChar(wstr, 1); + } + + operator wchar_t*() { return success ? (wchar_t *) value.c_str() : nullptr; } + operator wchar_t&() { return value[0]; } + + static PYBIND11_DESCR name() { return type_descr(_(PYBIND11_STRING_NAME)); } +}; + +template <typename T1, typename T2> class type_caster<std::pair<T1, T2>> { + typedef std::pair<T1, T2> type; +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; + const auto seq = reinterpret_borrow<sequence>(src); + if (seq.size() != size) + return false; + 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{}); + } + + static PYBIND11_DESCR name() { + return type_descr(_("Tuple[") + detail::concat(make_caster<Tuple>::name()...) + _("]")); + } + + template <typename T> using cast_op_type = type; + + operator type() { return implicit_cast(indices{}); } + +protected: + template <size_t... Is> + type implicit_cast(index_sequence<Is...>) { return type(cast_op<Tuple>(std::get<Is>(value))...); } + + 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)...}) + 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))... + }}; + for (const auto &entry: entries) + if (!entry) + return handle(); + tuple result(size); + int counter = 0; + for (auto & entry: entries) + PyTuple_SET_ITEM(result.ptr(), counter++, entry.release().ptr()); + return result.release(); + } + +protected: + std::tuple<make_caster<Tuple>...> value; +}; + +/// Type caster for holder types like std::shared_ptr, etc. +template <typename type, typename holder_type> class type_caster_holder : public type_caster_base<type> { +public: + using base = type_caster_base<type>; + 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, PyTypeObject *tobj) { + if (!src || !typeinfo) + return false; + if (src.is_none()) { + value = nullptr; + return true; + } + + 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(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; + } + } + + if (try_implicit_casts(src, convert)) + return true; + } + + if (convert) { + for (auto &converter : typeinfo->implicit_conversions) { + temp = reinterpret_steal<object>(converter(src.ptr(), typeinfo->type)); + if (load(temp, false)) + return true; + } + } + + return false; + } + + 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; + return true; + } else { + throw cast_error("Unable to cast from non-held to held instance (T& to Holder<T>) " +#if defined(NDEBUG) + "(compile in debug mode for type information)"); +#else + "of type '" + type_id<holder_type>() + "''"); +#endif + } + } + + template <typename T = holder_type, detail::enable_if_t<!std::is_constructible<T, const T &, type*>::value, int> = 0> + bool try_implicit_casts(handle, bool) { return false; } + + template <typename T = holder_type, detail::enable_if_t<std::is_constructible<T, const T &, type*>::value, int> = 0> + bool try_implicit_casts(handle src, bool convert) { + for (auto &cast : typeinfo->implicit_casts) { + type_caster_holder sub_caster(*cast.first); + if (sub_caster.load(src, convert)) { + value = cast.second(sub_caster.value); + holder = holder_type(sub_caster.holder, (type *) value); + return true; + } + } + 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 handle cast(const holder_type &src, return_value_policy, handle) { + return type_caster_generic::cast( + src.get(), return_value_policy::take_ownership, handle(), + src.get() ? &typeid(*src.get()) : nullptr, &typeid(type), + nullptr, nullptr, &src); + } + +protected: + holder_type holder; +}; + +/// Specialize for the common std::shared_ptr, so users don't need to +template <typename T> +class type_caster<std::shared_ptr<T>> : public type_caster_holder<T, std::shared_ptr<T>> { }; + +/// Create a specialization for custom holder types (silently ignores std::shared_ptr) +#define PYBIND11_DECLARE_HOLDER_TYPE(type, holder_type) \ + namespace pybind11 { namespace detail { \ + template <typename type> \ + class type_caster<holder_type, enable_if_t<!is_shared_ptr<holder_type>::value>> \ + : public type_caster_holder<type, holder_type> { }; \ + }} + +// PYBIND11_DECLARE_HOLDER_TYPE holder types: +template <typename base, typename holder> struct is_holder_type : + std::is_base_of<detail::type_caster_holder<base, holder>, detail::type_caster<holder>> {}; +// Specialization for always-supported unique_ptr holders: +template <typename base, typename deleter> struct is_holder_type<base, std::unique_ptr<base, deleter>> : + std::true_type {}; + +template <typename T> struct handle_type_name { static PYBIND11_DESCR name() { return _<T>(); } }; +template <> struct handle_type_name<bytes> { static PYBIND11_DESCR name() { return _(PYBIND11_BYTES_NAME); } }; +template <> struct handle_type_name<args> { static PYBIND11_DESCR name() { return _("*args"); } }; +template <> struct handle_type_name<kwargs> { static PYBIND11_DESCR name() { return _("**kwargs"); } }; + +template <typename type> +struct pyobject_caster { + template <typename T = type, enable_if_t<std::is_same<T, handle>::value, int> = 0> + bool load(handle src, bool /* convert */) { value = src; return static_cast<bool>(value); } + + template <typename T = type, enable_if_t<std::is_base_of<object, T>::value, int> = 0> + bool load(handle src, bool /* convert */) { + if (!isinstance<type>(src)) + return false; + value = reinterpret_borrow<type>(src); + return true; + } + + static handle cast(const handle &src, return_value_policy /* policy */, handle /* parent */) { + return src.inc_ref(); + } + PYBIND11_TYPE_CASTER(type, handle_type_name<type>::name()); +}; + +template <typename T> +class type_caster<T, enable_if_t<is_pyobject<T>::value>> : public pyobject_caster<T> { }; + +// Our conditions for enabling moving are quite restrictive: +// At compile time: +// - T needs to be a non-const, non-pointer, non-reference type +// - type_caster<T>::operator T&() must exist +// - the type must be move constructible (obviously) +// At run-time: +// - if the type is non-copy-constructible, the object must be the sole owner of the type (i.e. it +// must have ref_count() == 1)h +// If any of the above are not satisfied, we fall back to copying. +template <typename T, typename SFINAE = void> struct move_is_plain_type : std::false_type {}; +template <typename T> struct move_is_plain_type<T, enable_if_t< + !std::is_void<T>::value && !std::is_pointer<T>::value && !std::is_reference<T>::value && !std::is_const<T>::value + >> : std::true_type { }; +template <typename T, typename SFINAE = void> struct move_always : std::false_type {}; +template <typename T> struct move_always<T, enable_if_t< + move_is_plain_type<T>::value && + !std::is_copy_constructible<T>::value && std::is_move_constructible<T>::value && + std::is_same<decltype(std::declval<type_caster<T>>().operator T&()), T&>::value + >> : std::true_type { }; +template <typename T, typename SFINAE = void> struct move_if_unreferenced : std::false_type {}; +template <typename T> struct move_if_unreferenced<T, enable_if_t< + move_is_plain_type<T>::value && + !move_always<T>::value && std::is_move_constructible<T>::value && + std::is_same<decltype(std::declval<type_caster<T>>().operator T&()), T&>::value + >> : std::true_type { }; +template <typename T> using move_never = std::integral_constant<bool, !move_always<T>::value && !move_if_unreferenced<T>::value>; + +// Detect whether returning a `type` from a cast on type's type_caster is going to result in a +// reference or pointer to a local variable of the type_caster. Basically, only +// non-reference/pointer `type`s and reference/pointers from a type_caster_generic are safe; +// everything else returns a reference/pointer to a local variable. +template <typename type> using cast_is_temporary_value_reference = bool_constant< + (std::is_reference<type>::value || std::is_pointer<type>::value) && + !std::is_base_of<type_caster_generic, make_caster<type>>::value +>; + +// Basic python -> C++ casting; throws if casting fails +template <typename T, typename SFINAE> type_caster<T, SFINAE> &load_type(type_caster<T, SFINAE> &conv, const handle &handle) { + if (!conv.load(handle, true)) { +#if defined(NDEBUG) + throw cast_error("Unable to cast Python instance to C++ type (compile in debug mode for details)"); +#else + throw cast_error("Unable to cast Python instance of type " + + (std::string) str(handle.get_type()) + " to C++ type '" + type_id<T>() + "''"); +#endif + } + return conv; +} +// Wrapper around the above that also constructs and returns a type_caster +template <typename T> make_caster<T> load_type(const handle &handle) { + make_caster<T> conv; + load_type(conv, handle); + return conv; +} + +NAMESPACE_END(detail) + +// pytype -> C++ type +template <typename T, detail::enable_if_t<!detail::is_pyobject<T>::value, int> = 0> +T cast(const handle &handle) { + using namespace detail; + static_assert(!cast_is_temporary_value_reference<T>::value, + "Unable to cast type to reference: value is local to type caster"); + return cast_op<T>(load_type<T>(handle)); +} + +// pytype -> pytype (calls converting constructor) +template <typename T, detail::enable_if_t<detail::is_pyobject<T>::value, int> = 0> +T cast(const handle &handle) { return T(reinterpret_borrow<object>(handle)); } + +// C++ type -> py::object +template <typename T, detail::enable_if_t<!detail::is_pyobject<T>::value, int> = 0> +object cast(const T &value, return_value_policy policy = return_value_policy::automatic_reference, + handle parent = handle()) { + if (policy == return_value_policy::automatic) + policy = std::is_pointer<T>::value ? return_value_policy::take_ownership : return_value_policy::copy; + else if (policy == return_value_policy::automatic_reference) + policy = std::is_pointer<T>::value ? return_value_policy::reference : return_value_policy::copy; + return reinterpret_steal<object>(detail::make_caster<T>::cast(value, policy, parent)); +} + +template <typename T> T handle::cast() const { return pybind11::cast<T>(*this); } +template <> inline void handle::cast() const { return; } + +template <typename T> +detail::enable_if_t<detail::move_always<T>::value || detail::move_if_unreferenced<T>::value, T> move(object &&obj) { + if (obj.ref_count() > 1) +#if defined(NDEBUG) + throw cast_error("Unable to cast Python instance to C++ rvalue: instance has multiple references" + " (compile in debug mode for details)"); +#else + throw cast_error("Unable to move from Python " + (std::string) str(obj.get_type()) + + " instance to C++ " + type_id<T>() + " instance: instance has multiple references"); +#endif + + // Move into a temporary and return that, because the reference may be a local value of `conv` + T ret = std::move(detail::load_type<T>(obj).operator T&()); + return ret; +} + +// Calling cast() on an rvalue calls pybind::cast with the object rvalue, which does: +// - If we have to move (because T has no copy constructor), do it. This will fail if the moved +// object has multiple references, but trying to copy will fail to compile. +// - If both movable and copyable, check ref count: if 1, move; otherwise copy +// - Otherwise (not movable), copy. +template <typename T> detail::enable_if_t<detail::move_always<T>::value, T> cast(object &&object) { + return move<T>(std::move(object)); +} +template <typename T> detail::enable_if_t<detail::move_if_unreferenced<T>::value, T> cast(object &&object) { + if (object.ref_count() > 1) + return cast<T>(object); + else + return move<T>(std::move(object)); +} +template <typename T> detail::enable_if_t<detail::move_never<T>::value, T> cast(object &&object) { + return cast<T>(object); +} + +template <typename T> T object::cast() const & { return pybind11::cast<T>(*this); } +template <typename T> T object::cast() && { return pybind11::cast<T>(std::move(*this)); } +template <> inline void object::cast() const & { return; } +template <> inline void object::cast() && { return; } + +NAMESPACE_BEGIN(detail) + +// Declared in pytypes.h: +template <typename T, enable_if_t<!is_pyobject<T>::value, int>> +object object_or_cast(T &&o) { return pybind11::cast(std::forward<T>(o)); } + +struct overload_unused {}; // Placeholder type for the unneeded (and dead code) static variable in the OVERLOAD_INT macro +template <typename ret_type> using overload_caster_t = conditional_t< + cast_is_temporary_value_reference<ret_type>::value, make_caster<ret_type>, overload_unused>; + +// Trampoline use: for reference/pointer types to value-converted values, we do a value cast, then +// store the result in the given variable. For other types, this is a no-op. +template <typename T> enable_if_t<cast_is_temporary_value_reference<T>::value, T> cast_ref(object &&o, make_caster<T> &caster) { + return cast_op<T>(load_type(caster, o)); +} +template <typename T> enable_if_t<!cast_is_temporary_value_reference<T>::value, T> cast_ref(object &&, overload_unused &) { + pybind11_fail("Internal error: cast_ref fallback invoked"); } + +// Trampoline use: Having a pybind11::cast with an invalid reference type is going to static_assert, even +// though if it's in dead code, so we provide a "trampoline" to pybind11::cast that only does anything in +// cases where pybind11::cast is valid. +template <typename T> enable_if_t<!cast_is_temporary_value_reference<T>::value, T> cast_safe(object &&o) { + return pybind11::cast<T>(std::move(o)); } +template <typename T> enable_if_t<cast_is_temporary_value_reference<T>::value, T> cast_safe(object &&) { + pybind11_fail("Internal error: cast_safe fallback invoked"); } +template <> inline void cast_safe<void>(object &&) {} + +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); + 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) { +#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"); +#endif + } + } + tuple result(size); + int counter = 0; + for (auto &arg_value : args) + PyTuple_SET_ITEM(result.ptr(), counter++, arg_value.release().ptr()); + return result; +} + +/// Annotation for keyword arguments +struct arg { + constexpr explicit arg(const char *name) : name(name) { } + template <typename T> arg_v operator=(T &&value) const; + + const char *name; +}; + +/// Annotation for keyword arguments with values +struct arg_v : arg { + template <typename T> + arg_v(const char *name, T &&x, const char *descr = nullptr) + : arg(name), + value(reinterpret_steal<object>( + detail::make_caster<T>::cast(x, return_value_policy::automatic, {}) + )), + descr(descr) +#if !defined(NDEBUG) + , type(type_id<T>()) +#endif + { } + + object value; + const char *descr; +#if !defined(NDEBUG) + std::string type; +#endif +}; + +template <typename T> +arg_v arg::operator=(T &&value) const { return {name, std::forward<T>(value)}; } + +/// Alias for backward compatibility -- to be removed in version 2.0 +template <typename /*unused*/> using arg_t = arg_v; + +inline namespace literals { +/// String literal version of arg +constexpr arg operator"" _a(const char *name, size_t) { return arg(name); } +} + +NAMESPACE_BEGIN(detail) + +/// Helper class which loads arguments for C++ functions called from Python +template <typename... Args> +class argument_loader { + using itypes = type_list<intrinsic_t<Args>...>; + using indices = make_index_sequence<sizeof...(Args)>; + +public: + static constexpr auto has_kwargs = std::is_same<itypes, type_list<args, kwargs>>::value; + static constexpr auto has_args = has_kwargs || std::is_same<itypes, type_list<args>>::value; + + static PYBIND11_DESCR arg_names() { return detail::concat(make_caster<Args>::name()...); } + + bool load_args(handle args, handle kwargs, bool convert) { + return load_impl(args, kwargs, convert, itypes{}); + } + + 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 Func> + enable_if_t<std::is_void<Return>::value, void_type> call(Func &&f) { + call_impl<Return>(std::forward<Func>(f), indices{}); + return void_type(); + } + +private: + bool load_impl(handle args_, handle, bool convert, type_list<args>) { + std::get<0>(value).load(args_, convert); + return true; + } + + bool load_impl(handle args_, handle kwargs_, bool convert, type_list<args, kwargs>) { + std::get<0>(value).load(args_, convert); + std::get<1>(value).load(kwargs_, convert); + return true; + } + + bool load_impl(handle args, handle, bool convert, ... /* anything else */) { + return load_impl_sequence(args, convert, indices{}); + } + + static constexpr bool load_impl_sequence(handle, bool, index_sequence<>) { return true; } + + template <size_t... Is> + bool load_impl_sequence(handle src, bool convert, index_sequence<Is...>) { + for (bool r : {std::get<Is>(value).load(PyTuple_GET_ITEM(src.ptr(), Is), convert)...}) + 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))...); + } + +private: + std::tuple<make_caster<Args>...> value; +}; + +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> +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> +template <template<typename> class Predicate, typename... Ts> +constexpr int constexpr_last() { return constexpr_impl::last(0, -1, Predicate<Ts>::value...); } + +/// Helper class which collects only positional arguments for a Python function call. +/// A fancier version below can collect any argument, but this one is optimal for simple calls. +template <return_value_policy policy> +class simple_collector { +public: + template <typename... Ts> + explicit simple_collector(Ts &&...values) + : m_args(pybind11::make_tuple<policy>(std::forward<Ts>(values)...)) { } + + const tuple &args() const & { return m_args; } + dict kwargs() const { return {}; } + + tuple args() && { return std::move(m_args); } + + /// Call a Python function and pass the collected arguments + object call(PyObject *ptr) const { + PyObject *result = PyObject_CallObject(ptr, m_args.ptr()); + if (!result) + throw error_already_set(); + return reinterpret_steal<object>(result); + } + +private: + tuple m_args; +}; + +/// Helper class which collects positional, keyword, * and ** arguments for a Python function call +template <return_value_policy policy> +class unpacking_collector { +public: + template <typename... Ts> + explicit unpacking_collector(Ts &&...values) { + // Tuples aren't (easily) resizable so a list is needed for collection, + // but the actual function call strictly requires a tuple. + auto args_list = list(); + int _[] = { 0, (process(args_list, std::forward<Ts>(values)), 0)... }; + ignore_unused(_); + + m_args = std::move(args_list); + } + + const tuple &args() const & { return m_args; } + const dict &kwargs() const & { return m_kwargs; } + + tuple args() && { return std::move(m_args); } + dict kwargs() && { return std::move(m_kwargs); } + + /// Call a Python function and pass the collected arguments + object call(PyObject *ptr) const { + PyObject *result = PyObject_Call(ptr, m_args.ptr(), m_kwargs.ptr()); + if (!result) + throw error_already_set(); + return reinterpret_steal<object>(result); + } + +private: + template <typename T> + void process(list &args_list, T &&x) { + auto o = reinterpret_steal<object>(detail::make_caster<T>::cast(std::forward<T>(x), policy, {})); + if (!o) { +#if defined(NDEBUG) + argument_cast_error(); +#else + argument_cast_error(std::to_string(args_list.size()), type_id<T>()); +#endif + } + args_list.append(o); + } + + void process(list &args_list, detail::args_proxy ap) { + for (const auto &a : ap) + args_list.append(a); + } + + void process(list &/*args_list*/, arg_v a) { + if (m_kwargs.contains(a.name)) { +#if defined(NDEBUG) + multiple_values_error(); +#else + multiple_values_error(a.name); +#endif + } + if (!a.value) { +#if defined(NDEBUG) + argument_cast_error(); +#else + argument_cast_error(a.name, a.type); +#endif + } + m_kwargs[a.name] = a.value; + } + + void process(list &/*args_list*/, detail::kwargs_proxy kp) { + if (!kp) + return; + for (const auto &k : reinterpret_borrow<dict>(kp)) { + if (m_kwargs.contains(k.first)) { +#if defined(NDEBUG) + multiple_values_error(); +#else + multiple_values_error(str(k.first)); +#endif + } + m_kwargs[k.first] = k.second; + } + } + + [[noreturn]] static void multiple_values_error() { + throw type_error("Got multiple values for keyword argument " + "(compile in debug mode for details)"); + } + + [[noreturn]] static void multiple_values_error(std::string name) { + throw type_error("Got multiple values for keyword argument '" + name + "'"); + } + + [[noreturn]] static void argument_cast_error() { + throw cast_error("Unable to convert call argument to Python object " + "(compile in debug mode for details)"); + } + + [[noreturn]] static void argument_cast_error(std::string name, std::string type) { + throw cast_error("Unable to convert call argument '" + name + + "' of type '" + type + "' to Python object"); + } + +private: + tuple m_args; + dict m_kwargs; +}; + +/// Collect only positional arguments for a Python function call +template <return_value_policy policy, typename... Args, + typename = enable_if_t<all_of_t<is_positional, Args...>::value>> +simple_collector<policy> collect_arguments(Args &&...args) { + return simple_collector<policy>(std::forward<Args>(args)...); +} + +/// Collect all arguments, including keywords and unpacking (only instantiated when needed) +template <return_value_policy policy, typename... Args, + typename = enable_if_t<!all_of_t<is_positional, Args...>::value>> +unpacking_collector<policy> collect_arguments(Args &&...args) { + // Following argument order rules for generalized unpacking according to PEP 448 + static_assert( + constexpr_last<is_positional, Args...>() < constexpr_first<is_keyword_or_ds, Args...>() + && constexpr_last<is_s_unpacking, Args...>() < constexpr_first<is_ds_unpacking, Args...>(), + "Invalid function call: positional args must precede keywords and ** unpacking; " + "* unpacking must precede ** unpacking" + ); + return unpacking_collector<policy>(std::forward<Args>(args)...); +} + +template <typename Derived> +template <return_value_policy policy, typename... Args> +object object_api<Derived>::operator()(Args &&...args) const { + return detail::collect_arguments<policy>(std::forward<Args>(args)...).call(derived().ptr()); +} + +template <typename Derived> +template <return_value_policy policy, typename... Args> +object object_api<Derived>::call(Args &&...args) const { + return operator()<policy>(std::forward<Args>(args)...); +} + +NAMESPACE_END(detail) + +#define PYBIND11_MAKE_OPAQUE(Type) \ + namespace pybind11 { namespace detail { \ + template<> class type_caster<Type> : public type_caster_base<Type> { }; \ + }} + +NAMESPACE_END(pybind11) diff --git a/ext/pybind11/include/pybind11/chrono.h b/ext/pybind11/include/pybind11/chrono.h new file mode 100644 index 000000000..2b37f56f1 --- /dev/null +++ b/ext/pybind11/include/pybind11/chrono.h @@ -0,0 +1,160 @@ +/* + pybind11/chrono.h: Transparent conversion between std::chrono and python's datetime + + Copyright (c) 2016 Trent Houliston <trent@houliston.me> and + 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 <cmath> +#include <ctime> +#include <chrono> +#include <datetime.h> + +// Backport the PyDateTime_DELTA functions from Python3.3 if required +#ifndef PyDateTime_DELTA_GET_DAYS +#define PyDateTime_DELTA_GET_DAYS(o) (((PyDateTime_Delta*)o)->days) +#endif +#ifndef PyDateTime_DELTA_GET_SECONDS +#define PyDateTime_DELTA_GET_SECONDS(o) (((PyDateTime_Delta*)o)->seconds) +#endif +#ifndef PyDateTime_DELTA_GET_MICROSECONDS +#define PyDateTime_DELTA_GET_MICROSECONDS(o) (((PyDateTime_Delta*)o)->microseconds) +#endif + +NAMESPACE_BEGIN(pybind11) +NAMESPACE_BEGIN(detail) + +template <typename type> class duration_caster { +public: + typedef typename type::rep rep; + typedef typename type::period period; + + typedef std::chrono::duration<uint_fast32_t, std::ratio<86400>> days; + + bool load(handle src, bool) { + using namespace std::chrono; + + // Lazy initialise the PyDateTime import + if (!PyDateTimeAPI) { PyDateTime_IMPORT; } + + if (!src) return false; + // If invoked with datetime.delta object + if (PyDelta_Check(src.ptr())) { + value = type(duration_cast<duration<rep, period>>( + days(PyDateTime_DELTA_GET_DAYS(src.ptr())) + + seconds(PyDateTime_DELTA_GET_SECONDS(src.ptr())) + + microseconds(PyDateTime_DELTA_GET_MICROSECONDS(src.ptr())))); + return true; + } + // If invoked with a float we assume it is seconds and convert + else if (PyFloat_Check(src.ptr())) { + value = type(duration_cast<duration<rep, period>>(duration<double>(PyFloat_AsDouble(src.ptr())))); + return true; + } + else return false; + } + + // If this is a duration just return it back + static const std::chrono::duration<rep, period>& get_duration(const std::chrono::duration<rep, period> &src) { + return src; + } + + // If this is a time_point get the time_since_epoch + template <typename Clock> static std::chrono::duration<rep, period> get_duration(const std::chrono::time_point<Clock, std::chrono::duration<rep, period>> &src) { + return src.time_since_epoch(); + } + + static handle cast(const type &src, return_value_policy /* policy */, handle /* parent */) { + using namespace std::chrono; + + // Use overloaded function to get our duration from our source + // Works out if it is a duration or time_point and get the duration + auto d = get_duration(src); + + // Lazy initialise the PyDateTime import + if (!PyDateTimeAPI) { PyDateTime_IMPORT; } + + // Declare these special duration types so the conversions happen with the correct primitive types (int) + using dd_t = duration<int, std::ratio<86400>>; + using ss_t = duration<int, std::ratio<1>>; + using us_t = duration<int, std::micro>; + + return PyDelta_FromDSU(duration_cast<dd_t>(d).count(), + duration_cast<ss_t>(d % days(1)).count(), + duration_cast<us_t>(d % seconds(1)).count()); + } + + PYBIND11_TYPE_CASTER(type, _("datetime.timedelta")); +}; + +// This is for casting times on the system clock into datetime.datetime instances +template <typename Duration> class type_caster<std::chrono::time_point<std::chrono::system_clock, Duration>> { +public: + typedef std::chrono::time_point<std::chrono::system_clock, Duration> type; + bool load(handle src, bool) { + using namespace std::chrono; + + // Lazy initialise the PyDateTime import + if (!PyDateTimeAPI) { PyDateTime_IMPORT; } + + if (!src) return false; + if (PyDateTime_Check(src.ptr())) { + std::tm cal; + cal.tm_sec = PyDateTime_DATE_GET_SECOND(src.ptr()); + cal.tm_min = PyDateTime_DATE_GET_MINUTE(src.ptr()); + cal.tm_hour = PyDateTime_DATE_GET_HOUR(src.ptr()); + cal.tm_mday = PyDateTime_GET_DAY(src.ptr()); + cal.tm_mon = PyDateTime_GET_MONTH(src.ptr()) - 1; + cal.tm_year = PyDateTime_GET_YEAR(src.ptr()) - 1900; + cal.tm_isdst = -1; + + value = system_clock::from_time_t(std::mktime(&cal)) + microseconds(PyDateTime_DATE_GET_MICROSECOND(src.ptr())); + return true; + } + else return false; + } + + static handle cast(const std::chrono::time_point<std::chrono::system_clock, Duration> &src, return_value_policy /* policy */, handle /* parent */) { + using namespace std::chrono; + + // Lazy initialise the PyDateTime import + if (!PyDateTimeAPI) { PyDateTime_IMPORT; } + + std::time_t tt = system_clock::to_time_t(src); + // this function uses static memory so it's best to copy it out asap just in case + // otherwise other code that is using localtime may break this (not just python code) + std::tm localtime = *std::localtime(&tt); + + // Declare these special duration types so the conversions happen with the correct primitive types (int) + using us_t = duration<int, std::micro>; + + return PyDateTime_FromDateAndTime(localtime.tm_year + 1900, + localtime.tm_mon + 1, + localtime.tm_mday, + localtime.tm_hour, + localtime.tm_min, + localtime.tm_sec, + (duration_cast<us_t>(src.time_since_epoch() % seconds(1))).count()); + } + PYBIND11_TYPE_CASTER(type, _("datetime.datetime")); +}; + +// Other clocks that are not the system clock are not measured as datetime.datetime objects +// since they are not measured on calendar time. So instead we just make them timedeltas +// Or if they have passed us a time as a float we convert that +template <typename Clock, typename Duration> class type_caster<std::chrono::time_point<Clock, Duration>> +: public duration_caster<std::chrono::time_point<Clock, Duration>> { +}; + +template <typename Rep, typename Period> class type_caster<std::chrono::duration<Rep, Period>> +: public duration_caster<std::chrono::duration<Rep, Period>> { +}; + +NAMESPACE_END(detail) +NAMESPACE_END(pybind11) diff --git a/ext/pybind11/include/pybind11/common.h b/ext/pybind11/include/pybind11/common.h new file mode 100644 index 000000000..712c1a5d6 --- /dev/null +++ b/ext/pybind11/include/pybind11/common.h @@ -0,0 +1,595 @@ +/* + 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 + +#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 1 +#define PYBIND11_VERSION_MINOR 9 +#define PYBIND11_VERSION_PATCH dev0 + +/// Include Python header, disable linking to pythonX_d.lib on Windows in debug mode +#if defined(_MSC_VER) +# define HAVE_ROUND +# pragma warning(push) +# pragma warning(disable: 4510 4610 4512 4005) +# if _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_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_OB_TYPE(ht_type) (ht_type).ob_base.ob_base.ob_type +#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_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_OB_TYPE(ht_type) (ht_type).ob_type +#define PYBIND11_PLUGIN_IMPL(name) \ + extern "C" PYBIND11_EXPORT PyObject *init##name() +#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) "__" + +#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 (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 struture 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 +#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 a reference to the current 'internals' information +inline internals &get_internals(); + +/// Index sequence for convenient template metaprogramming involving tuples +#ifdef 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 + +/// 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 { }; + +/// from __cpp_future__ import (convenient aliases from C++14/17) +template <bool B> using bool_constant = std::integral_constant<bool, B>; +template <class T> using negation = bool_constant<!T::value>; +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; + +/// Compile-time integer sum +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...); } + +// Counts the number of types in the template parameter pack matching the predicate +#if !defined(_MSC_VER) +template <template<typename> class Predicate, typename... Ts> +using count_t = std::integral_constant<size_t, constexpr_sum(Predicate<Ts>::value...)>; +#else +// MSVC workaround (2015 Update 3 has issues with some member type aliases and constexpr) +template <template<typename> class Predicate, typename... Ts> struct count_t; +template <template<typename> class Predicate> struct count_t<Predicate> : std::integral_constant<size_t, 0> {}; +template <template<typename> class Predicate, class T, class... Ts> +struct count_t<Predicate, T, Ts...> : std::integral_constant<size_t, Predicate<T>::value + count_t<Predicate, Ts...>::value> {}; +#endif + +/// Return true if all/any Ts satify Predicate<T> +template <template<typename> class Predicate, typename... Ts> +using all_of_t = bool_constant<(count_t<Predicate, Ts...>::value == sizeof...(Ts))>; +template <template<typename> class Predicate, typename... Ts> +using any_of_t = bool_constant<(count_t<Predicate, Ts...>::value > 0)>; + +// 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((T*)nullptr)); +#else // MSVC2015 has trouble with decltype in template aliases +struct is_template_base_of : decltype(is_template_base_of_impl<Base>::check((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; } + +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; + virtual void set_error() const = 0; /// Set the error using the Python C API +}; + +#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); } + +/// Format strings for basic number types +#define PYBIND11_DECL_FMT(t, v) template<> struct format_descriptor<t> \ + { static constexpr const char* value = v; /* for backwards compatibility */ \ + static std::string format() { return value; } } + +template <typename T, typename SFINAE = void> struct format_descriptor { }; + +template <typename T> struct format_descriptor<T, detail::enable_if_t<std::is_integral<T>::value>> { + static constexpr const char c = "bBhHiIqQ"[detail::log2(sizeof(T))*2 + std::is_unsigned<T>::value]; + 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_integral<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); } +}; + +PYBIND11_DECL_FMT(float, "f"); +PYBIND11_DECL_FMT(double, "d"); +PYBIND11_DECL_FMT(bool, "?"); + +/// 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 2015 Update 2 +#if defined(PYBIND11_CPP14) || _MSC_FULL_VER >= 190023918 +#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) diff --git a/ext/pybind11/include/pybind11/complex.h b/ext/pybind11/include/pybind11/complex.h new file mode 100644 index 000000000..f767f354c --- /dev/null +++ b/ext/pybind11/include/pybind11/complex.h @@ -0,0 +1,47 @@ +/* + pybind11/complex.h: Complex number support + + 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 "pybind11.h" +#include <complex> + +/// glibc defines I as a macro which breaks things, e.g., boost template names +#ifdef I +# undef I +#endif + +NAMESPACE_BEGIN(pybind11) + +PYBIND11_DECL_FMT(std::complex<float>, "Zf"); +PYBIND11_DECL_FMT(std::complex<double>, "Zd"); + +NAMESPACE_BEGIN(detail) +template <typename T> class type_caster<std::complex<T>> { +public: + bool load(handle src, bool) { + if (!src) + return false; + Py_complex result = PyComplex_AsCComplex(src.ptr()); + if (result.real == -1.0 && PyErr_Occurred()) { + PyErr_Clear(); + return false; + } + value = std::complex<T>((T) result.real, (T) result.imag); + return true; + } + + static handle cast(const std::complex<T> &src, return_value_policy /* policy */, handle /* parent */) { + return PyComplex_FromDoubles((double) src.real(), (double) src.imag()); + } + + PYBIND11_TYPE_CASTER(std::complex<T>, _("complex")); +}; +NAMESPACE_END(detail) +NAMESPACE_END(pybind11) diff --git a/ext/pybind11/include/pybind11/descr.h b/ext/pybind11/include/pybind11/descr.h new file mode 100644 index 000000000..2c3fb3d13 --- /dev/null +++ b/ext/pybind11/include/pybind11/descr.h @@ -0,0 +1,183 @@ +/* + pybind11/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> + + 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 "common.h" + +NAMESPACE_BEGIN(pybind11) +NAMESPACE_BEGIN(detail) + +#if defined(PYBIND11_CPP14) /* Concatenate type signatures at compile time using C++14 */ + +template <size_t Size1, size_t Size2> class descr { + template <size_t Size1_, size_t Size2_> friend class descr; +public: + constexpr descr(char const (&text) [Size1+1], const std::type_info * const (&types)[Size2+1]) + : descr(text, types, + make_index_sequence<Size1>(), + make_index_sequence<Size2>()) { } + + constexpr const char *text() const { return m_text; } + constexpr const std::type_info * const * types() const { return m_types; } + + template <size_t OtherSize1, size_t OtherSize2> + constexpr descr<Size1 + OtherSize1, Size2 + OtherSize2> operator+(const descr<OtherSize1, OtherSize2> &other) const { + return concat(other, + make_index_sequence<Size1>(), + make_index_sequence<Size2>(), + make_index_sequence<OtherSize1>(), + make_index_sequence<OtherSize2>()); + } + +protected: + template <size_t... Indices1, size_t... Indices2> + constexpr descr( + char const (&text) [Size1+1], + const std::type_info * const (&types) [Size2+1], + index_sequence<Indices1...>, index_sequence<Indices2...>) + : m_text{text[Indices1]..., '\0'}, + m_types{types[Indices2]..., nullptr } {} + + template <size_t OtherSize1, size_t OtherSize2, size_t... Indices1, + size_t... Indices2, size_t... OtherIndices1, size_t... OtherIndices2> + constexpr descr<Size1 + OtherSize1, Size2 + OtherSize2> + concat(const descr<OtherSize1, OtherSize2> &other, + index_sequence<Indices1...>, index_sequence<Indices2...>, + index_sequence<OtherIndices1...>, index_sequence<OtherIndices2...>) const { + return descr<Size1 + OtherSize1, Size2 + OtherSize2>( + { m_text[Indices1]..., other.m_text[OtherIndices1]..., '\0' }, + { m_types[Indices2]..., other.m_types[OtherIndices2]..., nullptr } + ); + } + +protected: + char m_text[Size1 + 1]; + const std::type_info * m_types[Size2 + 1]; +}; + +template <size_t Size> constexpr descr<Size - 1, 0> _(char const(&text)[Size]) { + return descr<Size - 1, 0>(text, { nullptr }); +} + +template <size_t Rem, size_t... Digits> struct int_to_str : int_to_str<Rem/10, Rem%10, Digits...> { }; +template <size_t...Digits> struct int_to_str<0, Digits...> { + static constexpr auto digits = descr<sizeof...(Digits), 0>({ ('0' + Digits)..., '\0' }, { nullptr }); +}; + +// Ternary description (like std::conditional) +template <bool B, size_t Size1, size_t Size2> +constexpr enable_if_t<B, descr<Size1 - 1, 0>> _(char const(&text1)[Size1], char const(&)[Size2]) { + return _(text1); +} +template <bool B, size_t Size1, size_t Size2> +constexpr enable_if_t<!B, descr<Size2 - 1, 0>> _(char const(&)[Size1], char const(&text2)[Size2]) { + return _(text2); +} +template <bool B, size_t SizeA1, size_t SizeA2, size_t SizeB1, size_t SizeB2> +constexpr enable_if_t<B, descr<SizeA1, SizeA2>> _(descr<SizeA1, SizeA2> d, descr<SizeB1, SizeB2>) { return d; } +template <bool B, size_t SizeA1, size_t SizeA2, size_t SizeB1, size_t SizeB2> +constexpr enable_if_t<!B, descr<SizeB1, SizeB2>> _(descr<SizeA1, SizeA2>, descr<SizeB1, SizeB2> d) { return d; } + +template <size_t Size> auto constexpr _() -> decltype(int_to_str<Size / 10, Size % 10>::digits) { + return int_to_str<Size / 10, Size % 10>::digits; +} + +template <typename Type> constexpr descr<1, 1> _() { + return descr<1, 1>({ '%', '\0' }, { &typeid(Type), nullptr }); +} + +inline constexpr descr<0, 0> concat() { return _(""); } +template <size_t Size1, size_t Size2, typename... Args> auto constexpr concat(descr<Size1, Size2> descr) { return descr; } +template <size_t Size1, size_t Size2, typename... Args> auto constexpr concat(descr<Size1, Size2> descr, Args&&... args) { return descr + _(", ") + concat(args...); } +template <size_t Size1, size_t Size2> auto constexpr type_descr(descr<Size1, Size2> descr) { return _("{") + descr + _("}"); } + +#define PYBIND11_DESCR constexpr auto + +#else /* Simpler C++11 implementation based on run-time memory allocation and copying */ + +class descr { +public: + PYBIND11_NOINLINE descr(const char *text, const std::type_info * const * types) { + size_t nChars = len(text), nTypes = len(types); + m_text = new char[nChars]; + m_types = new const std::type_info *[nTypes]; + memcpy(m_text, text, nChars * sizeof(char)); + memcpy(m_types, types, nTypes * sizeof(const std::type_info *)); + } + + PYBIND11_NOINLINE descr friend operator+(descr &&d1, descr &&d2) { + descr r; + + size_t nChars1 = len(d1.m_text), nTypes1 = len(d1.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 + 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 + nTypes1 - 1, d2.m_types, nTypes2 * sizeof(std::type_info *)); + + delete[] d1.m_text; delete[] d1.m_types; + delete[] d2.m_text; delete[] d2.m_types; + + return r; + } + + char *text() { return m_text; } + const std::type_info * * types() { return m_types; } + +protected: + PYBIND11_NOINLINE descr() { } + + template <typename T> static size_t len(const T *ptr) { // return length including null termination + const T *it = ptr; + while (*it++ != (T) 0) + ; + return static_cast<size_t>(it - ptr); + } + + const std::type_info **m_types = nullptr; + char *m_text = nullptr; +}; + +/* The 'PYBIND11_NOINLINE inline' combinations below are intentional to get the desired linkage while producing as little object code as possible */ + +PYBIND11_NOINLINE inline descr _(const char *text) { + const std::type_info *types[1] = { nullptr }; + return descr(text, types); +} + +template <bool B> PYBIND11_NOINLINE enable_if_t<B, descr> _(const char *text1, const char *) { return _(text1); } +template <bool B> PYBIND11_NOINLINE enable_if_t<!B, descr> _(char const *, const char *text2) { return _(text2); } +template <bool B> PYBIND11_NOINLINE enable_if_t<B, descr> _(descr d, descr) { return d; } +template <bool B> PYBIND11_NOINLINE enable_if_t<!B, descr> _(descr, descr d) { return d; } + +template <typename Type> PYBIND11_NOINLINE descr _() { + const std::type_info *types[2] = { &typeid(Type), nullptr }; + return descr("%", types); +} + +template <size_t Size> PYBIND11_NOINLINE descr _() { + const std::type_info *types[1] = { nullptr }; + return descr(std::to_string(Size).c_str(), types); +} + +PYBIND11_NOINLINE inline descr concat() { return _(""); } +PYBIND11_NOINLINE inline descr concat(descr &&d) { return d; } +template <typename... Args> PYBIND11_NOINLINE descr concat(descr &&d, Args&&... args) { return std::move(d) + _(", ") + concat(std::forward<Args>(args)...); } +PYBIND11_NOINLINE inline descr type_descr(descr&& d) { return _("{") + std::move(d) + _("}"); } + +#define PYBIND11_DESCR ::pybind11::detail::descr +#endif + +NAMESPACE_END(detail) +NAMESPACE_END(pybind11) diff --git a/ext/pybind11/include/pybind11/eigen.h b/ext/pybind11/include/pybind11/eigen.h new file mode 100644 index 000000000..0a1208e16 --- /dev/null +++ b/ext/pybind11/include/pybind11/eigen.h @@ -0,0 +1,239 @@ +/* + pybind11/eigen.h: Transparent conversion for dense and sparse Eigen matrices + + 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 "numpy.h" + +#if defined(__INTEL_COMPILER) +# pragma warning(disable: 1682) // implicit conversion of a 64-bit integral type to a smaller integral type (potential portability problem) +#elif defined(__GNUG__) || defined(__clang__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wconversion" +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + +#include <Eigen/Core> +#include <Eigen/SparseCore> + +#if defined(__GNUG__) || defined(__clang__) +# pragma GCC diagnostic pop +#endif + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable: 4127) // warning C4127: Conditional expression is constant +#endif + +NAMESPACE_BEGIN(pybind11) +NAMESPACE_BEGIN(detail) + +template <typename T> using is_eigen_dense = is_template_base_of<Eigen::DenseBase, T>; +template <typename T> using is_eigen_sparse = is_template_base_of<Eigen::SparseMatrixBase, T>; +template <typename T> using is_eigen_ref = is_template_base_of<Eigen::RefBase, T>; + +// Test for objects inheriting from EigenBase<Derived> that aren't captured by the above. This +// basically covers anything that can be assigned to a dense matrix but that don't have a typical +// matrix data layout that can be copied from their .data(). For example, DiagonalMatrix and +// SelfAdjointView fall into this category. +template <typename T> using is_eigen_base = bool_constant< + is_template_base_of<Eigen::EigenBase, T>::value + && !is_eigen_dense<T>::value && !is_eigen_sparse<T>::value +>; + +template<typename Type> +struct type_caster<Type, enable_if_t<is_eigen_dense<Type>::value && !is_eigen_ref<Type>::value>> { + typedef typename Type::Scalar Scalar; + static constexpr bool rowMajor = Type::Flags & Eigen::RowMajorBit; + static constexpr bool isVector = Type::IsVectorAtCompileTime; + + bool load(handle src, bool) { + auto buf = array_t<Scalar>::ensure(src); + if (!buf) + return false; + + if (buf.ndim() == 1) { + typedef Eigen::InnerStride<> Strides; + if (!isVector && + !(Type::RowsAtCompileTime == Eigen::Dynamic && + Type::ColsAtCompileTime == Eigen::Dynamic)) + return false; + + if (Type::SizeAtCompileTime != Eigen::Dynamic && + buf.shape(0) != (size_t) Type::SizeAtCompileTime) + return false; + + Strides::Index n_elts = (Strides::Index) buf.shape(0); + Strides::Index unity = 1; + + value = Eigen::Map<Type, 0, Strides>( + buf.mutable_data(), + rowMajor ? unity : n_elts, + rowMajor ? n_elts : unity, + Strides(buf.strides(0) / sizeof(Scalar)) + ); + } else if (buf.ndim() == 2) { + typedef Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic> Strides; + + if ((Type::RowsAtCompileTime != Eigen::Dynamic && buf.shape(0) != (size_t) Type::RowsAtCompileTime) || + (Type::ColsAtCompileTime != Eigen::Dynamic && buf.shape(1) != (size_t) Type::ColsAtCompileTime)) + return false; + + value = Eigen::Map<Type, 0, Strides>( + buf.mutable_data(), + typename Strides::Index(buf.shape(0)), + typename Strides::Index(buf.shape(1)), + Strides(buf.strides(rowMajor ? 0 : 1) / sizeof(Scalar), + buf.strides(rowMajor ? 1 : 0) / sizeof(Scalar)) + ); + } else { + return false; + } + return true; + } + + static handle cast(const Type &src, return_value_policy /* policy */, handle /* parent */) { + if (isVector) { + return array( + { (size_t) src.size() }, // shape + { sizeof(Scalar) * static_cast<size_t>(src.innerStride()) }, // strides + src.data() // data + ).release(); + } else { + return array( + { (size_t) src.rows(), // shape + (size_t) src.cols() }, + { sizeof(Scalar) * static_cast<size_t>(src.rowStride()), // strides + sizeof(Scalar) * static_cast<size_t>(src.colStride()) }, + src.data() // data + ).release(); + } + } + + PYBIND11_TYPE_CASTER(Type, _("numpy.ndarray[") + npy_format_descriptor<Scalar>::name() + + _("[") + rows() + _(", ") + cols() + _("]]")); + +protected: + template <typename T = Type, enable_if_t<T::RowsAtCompileTime == Eigen::Dynamic, int> = 0> + static PYBIND11_DESCR rows() { return _("m"); } + template <typename T = Type, enable_if_t<T::RowsAtCompileTime != Eigen::Dynamic, int> = 0> + static PYBIND11_DESCR rows() { return _<T::RowsAtCompileTime>(); } + template <typename T = Type, enable_if_t<T::ColsAtCompileTime == Eigen::Dynamic, int> = 0> + static PYBIND11_DESCR cols() { return _("n"); } + template <typename T = Type, enable_if_t<T::ColsAtCompileTime != Eigen::Dynamic, int> = 0> + static PYBIND11_DESCR cols() { return _<T::ColsAtCompileTime>(); } +}; + +// Eigen::Ref<Derived> satisfies is_eigen_dense, but isn't constructable, so it needs a special +// type_caster to handle argument copying/forwarding. +template <typename CVDerived, int Options, typename StrideType> +struct type_caster<Eigen::Ref<CVDerived, Options, StrideType>> { +protected: + using Type = Eigen::Ref<CVDerived, Options, StrideType>; + using Derived = typename std::remove_const<CVDerived>::type; + using DerivedCaster = type_caster<Derived>; + DerivedCaster derived_caster; + std::unique_ptr<Type> value; +public: + bool load(handle src, bool convert) { if (derived_caster.load(src, convert)) { value.reset(new Type(derived_caster.operator Derived&())); return true; } return false; } + static handle cast(const Type &src, return_value_policy policy, handle parent) { return DerivedCaster::cast(src, policy, parent); } + static handle cast(const Type *src, return_value_policy policy, handle parent) { return DerivedCaster::cast(*src, policy, parent); } + + static PYBIND11_DESCR name() { return DerivedCaster::name(); } + + operator Type*() { return value.get(); } + operator Type&() { if (!value) pybind11_fail("Eigen::Ref<...> value not loaded"); return *value; } + template <typename _T> using cast_op_type = pybind11::detail::cast_op_type<_T>; +}; + +// type_caster for special matrix types (e.g. DiagonalMatrix): load() is not supported, but we can +// cast them into the python domain by first copying to a regular Eigen::Matrix, then casting that. +template <typename Type> +struct type_caster<Type, enable_if_t<is_eigen_base<Type>::value && !is_eigen_ref<Type>::value>> { +protected: + using Matrix = Eigen::Matrix<typename Type::Scalar, Eigen::Dynamic, Eigen::Dynamic>; + using MatrixCaster = type_caster<Matrix>; +public: + [[noreturn]] bool load(handle, bool) { pybind11_fail("Unable to load() into specialized EigenBase object"); } + static handle cast(const Type &src, return_value_policy policy, handle parent) { return MatrixCaster::cast(Matrix(src), policy, parent); } + static handle cast(const Type *src, return_value_policy policy, handle parent) { return MatrixCaster::cast(Matrix(*src), policy, parent); } + + static PYBIND11_DESCR name() { return MatrixCaster::name(); } + + [[noreturn]] operator Type*() { pybind11_fail("Loading not supported for specialized EigenBase object"); } + [[noreturn]] operator Type&() { pybind11_fail("Loading not supported for specialized EigenBase object"); } + template <typename _T> using cast_op_type = pybind11::detail::cast_op_type<_T>; +}; + +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 typename Type::Index Index; + static constexpr bool rowMajor = Type::Flags & Eigen::RowMajorBit; + + bool load(handle src, bool) { + if (!src) + return false; + + auto obj = reinterpret_borrow<object>(src); + object sparse_module = module::import("scipy.sparse"); + object matrix_type = sparse_module.attr( + rowMajor ? "csr_matrix" : "csc_matrix"); + + if (obj.get_type() != matrix_type.ptr()) { + try { + obj = matrix_type(obj); + } catch (const error_already_set &) { + return false; + } + } + + auto values = array_t<Scalar>((object) obj.attr("data")); + auto innerIndices = array_t<StorageIndex>((object) obj.attr("indices")); + auto outerIndices = array_t<StorageIndex>((object) obj.attr("indptr")); + auto shape = pybind11::tuple((pybind11::object) obj.attr("shape")); + auto nnz = obj.attr("nnz").cast<Index>(); + + if (!values || !innerIndices || !outerIndices) + return false; + + value = Eigen::MappedSparseMatrix<Scalar, Type::Flags, StorageIndex>( + shape[0].cast<Index>(), shape[1].cast<Index>(), nnz, + outerIndices.mutable_data(), innerIndices.mutable_data(), values.mutable_data()); + + return true; + } + + static handle cast(const Type &src, return_value_policy /* policy */, handle /* parent */) { + const_cast<Type&>(src).makeCompressed(); + + 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()); + + return matrix_type( + std::make_tuple(data, innerIndices, outerIndices), + std::make_pair(src.rows(), src.cols()) + ).release(); + } + + PYBIND11_TYPE_CASTER(Type, _<(Type::Flags & Eigen::RowMajorBit) != 0>("scipy.sparse.csr_matrix[", "scipy.sparse.csc_matrix[") + + npy_format_descriptor<Scalar>::name() + _("]")); +}; + +NAMESPACE_END(detail) +NAMESPACE_END(pybind11) + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif diff --git a/ext/pybind11/include/pybind11/eval.h b/ext/pybind11/include/pybind11/eval.h new file mode 100644 index 000000000..204427d77 --- /dev/null +++ b/ext/pybind11/include/pybind11/eval.h @@ -0,0 +1,105 @@ +/* + pybind11/exec.h: Support for evaluating Python expressions and statements + from strings and files + + Copyright (c) 2016 Klemens Morgenstern <klemens.morgenstern@ed-chemnitz.de> and + 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 + +#pragma once + +#include "pybind11.h" + +NAMESPACE_BEGIN(pybind11) + +enum eval_mode { + /// Evaluate a string containing an isolated expression + eval_expr, + + /// Evaluate a string containing a single statement. Returns \c none + eval_single_statement, + + /// Evaluate a string containing a sequence of statement. Returns \c none + eval_statements +}; + +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(); + } + if (!local) + local = global; + + /* PyRun_String does not accept a PyObject / encoding specifier, + this seems to be the only alternative */ + std::string buffer = "# -*- coding: utf-8 -*-\n" + (std::string) expr; + + int start; + switch (mode) { + case eval_expr: start = Py_eval_input; break; + case eval_single_statement: start = Py_single_input; break; + case eval_statements: start = Py_file_input; break; + default: pybind11_fail("invalid evaluation mode"); + } + + PyObject *result = PyRun_String(buffer.c_str(), start, global.ptr(), local.ptr()); + if (!result) + throw error_already_set(); + return reinterpret_steal<object>(result); +} + +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(); + } + if (!local) + local = global; + + int start; + switch (mode) { + case eval_expr: start = Py_eval_input; break; + case eval_single_statement: start = Py_single_input; break; + case eval_statements: start = Py_file_input; break; + default: pybind11_fail("invalid evaluation mode"); + } + + int closeFile = 1; + std::string fname_str = (std::string) fname; +#if PY_VERSION_HEX >= 0x03040000 + FILE *f = _Py_fopen_obj(fname.ptr(), "r"); +#elif PY_VERSION_HEX >= 0x03000000 + FILE *f = _Py_fopen(fname.ptr(), "r"); +#else + /* No unicode support in open() :( */ + auto fobj = reinterpret_steal<object>(PyFile_FromString( + const_cast<char *>(fname_str.c_str()), + const_cast<char*>("r"))); + FILE *f = nullptr; + if (fobj) + f = PyFile_AsFile(fobj.ptr()); + closeFile = 0; +#endif + if (!f) { + PyErr_Clear(); + pybind11_fail("File \"" + fname_str + "\" could not be opened!"); + } + + PyObject *result = PyRun_FileEx(f, fname_str.c_str(), start, global.ptr(), + local.ptr(), closeFile); + if (!result) + throw error_already_set(); + return reinterpret_steal<object>(result); +} + +NAMESPACE_END(pybind11) diff --git a/ext/pybind11/include/pybind11/functional.h b/ext/pybind11/include/pybind11/functional.h new file mode 100644 index 000000000..f1b0ebbbf --- /dev/null +++ b/ext/pybind11/include/pybind11/functional.h @@ -0,0 +1,79 @@ +/* + pybind11/functional.h: std::function<> support + + 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 "pybind11.h" +#include <functional> + +NAMESPACE_BEGIN(pybind11) +NAMESPACE_BEGIN(detail) + +template <typename Return, typename... Args> struct type_caster<std::function<Return(Args...)>> { + typedef std::function<Return(Args...)> type; + typedef typename std::conditional<std::is_same<Return, void>::value, void_type, Return>::type retval_type; +public: + bool load(handle src_, bool) { + if (src_.is_none()) + return true; + + src_ = detail::get_function(src_); + if (!src_ || !PyCallable_Check(src_.ptr())) + return false; + + /* + When passing a C++ function as an argument to another C++ + function via Python, every function call would normally involve + a full C++ -> Python -> C++ roundtrip, which can be prohibitive. + Here, we try to at least detect the case where the function is + 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_GetSelf(src_.ptr())); + auto rec = (function_record *) c; + using FunctionType = Return (*) (Args...); + + if (rec && rec->is_stateless && rec->data[1] == &typeid(FunctionType)) { + struct capture { FunctionType f; }; + value = ((capture *) &rec->data)->f; + return true; + } + } + + auto src = reinterpret_borrow<object>(src_); + value = [src](Args... args) -> Return { + gil_scoped_acquire acq; + object retval(src(std::move(args)...)); + /* Visual studio 2015 parser issue: need parentheses around this expression */ + return (retval.template cast<Return>()); + }; + return true; + } + + template <typename Func> + static handle cast(Func &&f_, return_value_policy policy, handle /* parent */) { + if (!f_) + return none().inc_ref(); + + auto result = f_.template target<Return (*)(Args...)>(); + if (result) + return cpp_function(*result, policy).release(); + else + return cpp_function(std::forward<Func>(f_), policy).release(); + } + + PYBIND11_TYPE_CASTER(type, _("Callable[[") + + argument_loader<Args...>::arg_names() + _("], ") + + type_caster<retval_type>::name() + + _("]")); +}; + +NAMESPACE_END(detail) +NAMESPACE_END(pybind11) diff --git a/ext/pybind11/include/pybind11/numpy.h b/ext/pybind11/include/pybind11/numpy.h new file mode 100644 index 000000000..e6f4efdf9 --- /dev/null +++ b/ext/pybind11/include/pybind11/numpy.h @@ -0,0 +1,1169 @@ +/* + pybind11/numpy.h: Basic NumPy support, vectorize() wrapper + + 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 "pybind11.h" +#include "complex.h" +#include <numeric> +#include <algorithm> +#include <array> +#include <cstdlib> +#include <cstring> +#include <sstream> +#include <string> +#include <initializer_list> +#include <functional> +#include <utility> +#include <typeindex> + +#if defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable: 4127) // warning C4127: Conditional expression is constant +#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 + 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"); + +NAMESPACE_BEGIN(pybind11) +NAMESPACE_BEGIN(detail) +template <typename type, typename SFINAE = void> struct npy_format_descriptor { }; +template <typename type> struct is_pod_struct; + +struct PyArrayDescr_Proxy { + PyObject_HEAD + PyObject *typeobj; + char kind; + char type; + char byteorder; + char flags; + int type_num; + int elsize; + int alignment; + char *subarray; + PyObject *fields; + PyObject *names; +}; + +struct PyArray_Proxy { + PyObject_HEAD + char *data; + int nd; + ssize_t *dimensions; + ssize_t *strides; + PyObject *base; + PyObject *descr; + int flags; +}; + +struct PyVoidScalarObject_Proxy { + PyObject_VAR_HEAD + char *obval; + PyArrayDescr_Proxy *descr; + int flags; + PyObject *base; +}; + +struct numpy_type_info { + PyObject* dtype_ptr; + std::string format_str; +}; + +struct numpy_internals { + std::unordered_map<std::type_index, numpy_type_info> registered_dtypes; + + numpy_type_info *get_type_info(const std::type_info& tinfo, bool throw_if_missing = true) { + auto it = registered_dtypes.find(std::type_index(tinfo)); + if (it != registered_dtypes.end()) + return &(it->second); + if (throw_if_missing) + pybind11_fail(std::string("NumPy type info missing for ") + tinfo.name()); + return nullptr; + } + + template<typename T> numpy_type_info *get_type_info(bool throw_if_missing = true) { + return get_type_info(typeid(typename std::remove_cv<T>::type), throw_if_missing); + } +}; + +inline PYBIND11_NOINLINE void load_numpy_internals(numpy_internals* &ptr) { + ptr = &get_or_create_shared_data<numpy_internals>("_numpy_internals"); +} + +inline numpy_internals& get_numpy_internals() { + static numpy_internals* ptr = nullptr; + if (!ptr) + load_numpy_internals(ptr); + return *ptr; +} + +struct npy_api { + enum constants { + NPY_C_CONTIGUOUS_ = 0x0001, + NPY_F_CONTIGUOUS_ = 0x0002, + NPY_ARRAY_OWNDATA_ = 0x0004, + NPY_ARRAY_FORCECAST_ = 0x0010, + NPY_ENSURE_ARRAY_ = 0x0040, + NPY_ARRAY_ALIGNED_ = 0x0100, + NPY_ARRAY_WRITEABLE_ = 0x0400, + NPY_BOOL_ = 0, + NPY_BYTE_, NPY_UBYTE_, + NPY_SHORT_, NPY_USHORT_, + NPY_INT_, NPY_UINT_, + NPY_LONG_, NPY_ULONG_, + NPY_LONGLONG_, NPY_ULONGLONG_, + NPY_FLOAT_, NPY_DOUBLE_, NPY_LONGDOUBLE_, + NPY_CFLOAT_, NPY_CDOUBLE_, NPY_CLONGDOUBLE_, + NPY_OBJECT_ = 17, + NPY_STRING_, NPY_UNICODE_, NPY_VOID_ + }; + + static npy_api& get() { + static npy_api api = lookup(); + return api; + } + + bool PyArray_Check_(PyObject *obj) const { + return (bool) PyObject_TypeCheck(obj, PyArray_Type_); + } + bool PyArrayDescr_Check_(PyObject *obj) const { + return (bool) PyObject_TypeCheck(obj, PyArrayDescr_Type_); + } + + PyObject *(*PyArray_DescrFromType_)(int); + PyObject *(*PyArray_NewFromDescr_) + (PyTypeObject *, PyObject *, int, Py_intptr_t *, + Py_intptr_t *, void *, int, PyObject *); + PyObject *(*PyArray_DescrNewFromType_)(int); + PyObject *(*PyArray_NewCopy_)(PyObject *, int); + PyTypeObject *PyArray_Type_; + PyTypeObject *PyVoidArrType_Type_; + PyTypeObject *PyArrayDescr_Type_; + PyObject *(*PyArray_DescrFromScalar_)(PyObject *); + PyObject *(*PyArray_FromAny_) (PyObject *, PyObject *, int, int, int, PyObject *); + int (*PyArray_DescrConverter_) (PyObject *, PyObject **); + bool (*PyArray_EquivTypes_) (PyObject *, PyObject *); + int (*PyArray_GetArrayParamsFromObject_)(PyObject *, PyObject *, char, PyObject **, int *, + Py_ssize_t *, PyObject **, PyObject *); + PyObject *(*PyArray_Squeeze_)(PyObject *); +private: + enum functions { + 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_NewCopy = 85, + API_PyArray_NewFromDescr = 94, + API_PyArray_DescrNewFromType = 9, + API_PyArray_DescrConverter = 174, + API_PyArray_EquivTypes = 182, + API_PyArray_GetArrayParamsFromObject = 278, + API_PyArray_Squeeze = 136 + }; + + static npy_api lookup() { + module m = module::import("numpy.core.multiarray"); + auto c = m.attr("_ARRAY_API"); +#if PY_MAJOR_VERSION >= 3 + void **api_ptr = (void **) PyCapsule_GetPointer(c.ptr(), NULL); +#else + void **api_ptr = (void **) PyCObject_AsVoidPtr(c.ptr()); +#endif + npy_api api; +#define DECL_NPY_API(Func) api.Func##_ = (decltype(api.Func##_)) api_ptr[API_##Func]; + 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_NewCopy); + DECL_NPY_API(PyArray_NewFromDescr); + DECL_NPY_API(PyArray_DescrNewFromType); + DECL_NPY_API(PyArray_DescrConverter); + DECL_NPY_API(PyArray_EquivTypes); + DECL_NPY_API(PyArray_GetArrayParamsFromObject); + DECL_NPY_API(PyArray_Squeeze); +#undef DECL_NPY_API + return api; + } +}; + +inline PyArray_Proxy* array_proxy(void* ptr) { + return reinterpret_cast<PyArray_Proxy*>(ptr); +} + +inline const PyArray_Proxy* array_proxy(const void* ptr) { + return reinterpret_cast<const PyArray_Proxy*>(ptr); +} + +inline PyArrayDescr_Proxy* array_descriptor_proxy(PyObject* ptr) { + return reinterpret_cast<PyArrayDescr_Proxy*>(ptr); +} + +inline const PyArrayDescr_Proxy* array_descriptor_proxy(const PyObject* ptr) { + return reinterpret_cast<const PyArrayDescr_Proxy*>(ptr); +} + +inline bool check_flags(const void* ptr, int flag) { + return (flag == (array_proxy(ptr)->flags & flag)); +} + +NAMESPACE_END(detail) + +class dtype : public object { +public: + PYBIND11_OBJECT_DEFAULT(dtype, object, detail::npy_api::get().PyArrayDescr_Check_); + + explicit dtype(const buffer_info &info) { + dtype descr(_dtype_from_pep3118()(PYBIND11_STR_TYPE(info.format))); + // If info.itemsize == 0, use the value calculated from the format string + m_ptr = descr.strip_padding(info.itemsize ? info.itemsize : descr.itemsize()).release().ptr(); + } + + explicit dtype(const std::string &format) { + m_ptr = from_args(pybind11::str(format)).release().ptr(); + } + + dtype(const char *format) : dtype(std::string(format)) { } + + dtype(list names, list formats, list offsets, size_t itemsize) { + dict args; + args["names"] = names; + args["formats"] = formats; + args["offsets"] = offsets; + args["itemsize"] = pybind11::int_(itemsize); + m_ptr = from_args(args).release().ptr(); + } + + /// This is essentially the same as calling numpy.dtype(args) in Python. + static dtype from_args(object args) { + PyObject *ptr = nullptr; + if (!detail::npy_api::get().PyArray_DescrConverter_(args.release().ptr(), &ptr) || !ptr) + throw error_already_set(); + return reinterpret_steal<dtype>(ptr); + } + + /// Return dtype associated with a C++ type. + template <typename T> static dtype of() { + return detail::npy_format_descriptor<typename std::remove_cv<T>::type>::dtype(); + } + + /// Size of the data type in bytes. + size_t itemsize() const { + return (size_t) detail::array_descriptor_proxy(m_ptr)->elsize; + } + + /// Returns true for structured data types. + bool has_fields() const { + return detail::array_descriptor_proxy(m_ptr)->names != nullptr; + } + + /// Single-character type code. + char kind() const { + return detail::array_descriptor_proxy(m_ptr)->kind; + } + +private: + static object _dtype_from_pep3118() { + static PyObject *obj = module::import("numpy.core._internal") + .attr("_dtype_from_pep3118").cast<object>().release().ptr(); + return reinterpret_borrow<object>(obj); + } + + dtype strip_padding(size_t itemsize) { + // Recursively strip all void fields with empty names that are generated for + // padding fields (as of NumPy v1.11). + if (!has_fields()) + return *this; + + struct field_descr { PYBIND11_STR_TYPE name; object format; pybind11::int_ offset; }; + std::vector<field_descr> field_descriptors; + + for (auto field : attr("fields").attr("items")()) { + auto spec = field.cast<tuple>(); + auto name = spec[0].cast<pybind11::str>(); + auto format = spec[1].cast<tuple>()[0].cast<dtype>(); + auto offset = spec[1].cast<tuple>()[1].cast<pybind11::int_>(); + if (!len(name) && format.kind() == 'V') + continue; + field_descriptors.push_back({(PYBIND11_STR_TYPE) name, format.strip_padding(format.itemsize()), offset}); + } + + std::sort(field_descriptors.begin(), field_descriptors.end(), + [](const field_descr& a, const field_descr& b) { + return a.offset.cast<int>() < b.offset.cast<int>(); + }); + + list names, formats, offsets; + for (auto& descr : field_descriptors) { + names.append(descr.name); + formats.append(descr.format); + offsets.append(descr.offset); + } + return dtype(names, formats, offsets, itemsize); + } +}; + +class array : public buffer { +public: + PYBIND11_OBJECT_CVT(array, buffer, detail::npy_api::get().PyArray_Check_, raw_array) + + enum { + c_style = detail::npy_api::NPY_C_CONTIGUOUS_, + f_style = detail::npy_api::NPY_F_CONTIGUOUS_, + forcecast = detail::npy_api::NPY_ARRAY_FORCECAST_ + }; + + 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()) + pybind11_fail("NumPy: shape ndim doesn't match strides ndim"); + auto descr = dt; + + int flags = 0; + if (base && ptr) { + if (isinstance<array>(base)) + /* Copy flags from base (except baseship bit) */ + flags = reinterpret_borrow<array>(base).flags() & ~detail::npy_api::NPY_ARRAY_OWNDATA_; + else + /* Writable by default, easy to downgrade later on if needed */ + flags = detail::npy_api::NPY_ARRAY_WRITEABLE_; + } + + auto tmp = reinterpret_steal<object>(api.PyArray_NewFromDescr_( + api.PyArray_Type_, descr.release().ptr(), (int) ndim, (Py_intptr_t *) shape.data(), + (Py_intptr_t *) strides.data(), const_cast<void *>(ptr), flags, nullptr)); + if (!tmp) + pybind11_fail("NumPy: unable to create array!"); + if (ptr) { + if (base) { + detail::array_proxy(tmp.ptr())->base = base.inc_ref().ptr(); + } else { + tmp = reinterpret_steal<object>(api.PyArray_NewCopy_(tmp.ptr(), -1 /* any order */)); + } + } + 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, size_t count, const void *ptr = nullptr, + handle base = handle()) + : array(dt, std::vector<size_t>{ 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, (void *) 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) { } + + template <typename T> + array(size_t count, const T *ptr, handle base = handle()) + : array(std::vector<size_t>{ count }, ptr, base) { } + + explicit array(const buffer_info &info) + : array(pybind11::dtype(info), info.shape, info.strides, info.ptr) { } + + /// Array descriptor (dtype) + pybind11::dtype dtype() const { + return reinterpret_borrow<pybind11::dtype>(detail::array_proxy(m_ptr)->descr); + } + + /// Total number of elements + size_t size() const { + return std::accumulate(shape(), shape() + ndim(), (size_t) 1, std::multiplies<size_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; + } + + /// Total number of bytes + size_t nbytes() const { + return size() * itemsize(); + } + + /// Number of dimensions + size_t ndim() const { + return (size_t) detail::array_proxy(m_ptr)->nd; + } + + /// Base object + object base() const { + return reinterpret_borrow<object>(detail::array_proxy(m_ptr)->base); + } + + /// Dimensions of the array + const size_t* shape() const { + return reinterpret_cast<const size_t *>(detail::array_proxy(m_ptr)->dimensions); + } + + /// Dimension along a given axis + size_t shape(size_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); + } + + /// Stride along a given axis + size_t strides(size_t dim) const { + if (dim >= ndim()) + fail_dim_check(dim, "invalid axis"); + return strides()[dim]; + } + + /// Return the NumPy array flags + int flags() const { + return detail::array_proxy(m_ptr)->flags; + } + + /// If set, the array is writeable (otherwise the buffer is read-only) + bool writeable() const { + return detail::check_flags(m_ptr, detail::npy_api::NPY_ARRAY_WRITEABLE_); + } + + /// If set, the array owns the data (will be freed when the array is deleted) + bool owndata() const { + return detail::check_flags(m_ptr, detail::npy_api::NPY_ARRAY_OWNDATA_); + } + + /// Pointer to the contained data. If index is not provided, points to the + /// beginning of the buffer. May throw if the index would lead to out of bounds access. + template<typename... Ix> const void* data(Ix... index) const { + return static_cast<const void *>(detail::array_proxy(m_ptr)->data + offset_at(index...)); + } + + /// Mutable pointer to the contained data. If index is not provided, points to the + /// beginning of the buffer. May throw if the index would lead to out of bounds access. + /// May throw if the array is not writeable. + template<typename... Ix> void* mutable_data(Ix... index) { + check_writeable(); + return static_cast<void *>(detail::array_proxy(m_ptr)->data + offset_at(index...)); + } + + /// 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()) + fail_dim_check(sizeof...(index), "too many indices for an array"); + return byte_offset(size_t(index)...); + } + + size_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 { + return offset_at(index...) / itemsize(); + } + + /// Return a new view with all of the dimensions of length 1 removed + array squeeze() { + auto& api = detail::npy_api::get(); + return reinterpret_steal<array>(api.PyArray_Squeeze_(m_ptr)); + } + + /// 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) { + auto result = reinterpret_steal<array>(raw_array(h.ptr(), ExtraFlags)); + if (!result) + PyErr_Clear(); + return result; + } + +protected: + template<typename, typename> friend struct detail::npy_format_descriptor; + + void fail_dim_check(size_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 { + check_dimensions(index...); + return byte_offset_unsafe(index...); + } + + template<size_t dim = 0, typename... Ix> size_t byte_offset_unsafe(size_t i, Ix... index) const { + return i * strides()[dim] + byte_offset_unsafe<dim + 1>(index...); + } + + template<size_t dim = 0> size_t byte_offset_unsafe() const { return 0; } + + void check_writeable() const { + if (!writeable()) + throw std::runtime_error("array is not writeable"); + } + + static std::vector<size_t> default_strides(const std::vector<size_t>& shape, size_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]; + } + return strides; + } + + template<typename... Ix> void check_dimensions(Ix... index) const { + check_dimensions_impl(size_t(0), shape(), size_t(index)...); + } + + void check_dimensions_impl(size_t, const size_t*) const { } + + template<typename... Ix> void check_dimensions_impl(size_t axis, const size_t* shape, size_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) + + " with size " + std::to_string(*shape)); + } + check_dimensions_impl(axis + 1, shape + 1, index...); + } + + /// Create array from any object -- always returns a new reference + static PyObject *raw_array(PyObject *ptr, int ExtraFlags = 0) { + if (ptr == nullptr) + return nullptr; + return detail::npy_api::get().PyArray_FromAny_( + ptr, nullptr, 0, 0, detail::npy_api::NPY_ENSURE_ARRAY_ | ExtraFlags, nullptr); + } +}; + +template <typename T, int ExtraFlags = array::forcecast> class array_t : public array { +public: + 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) { } + + PYBIND11_DEPRECATED("Use array_t<T>::ensure() instead") + array_t(handle h, bool is_borrowed) : array(raw_array_t(h.ptr()), stolen) { + if (!m_ptr) PyErr_Clear(); + if (!is_borrowed) Py_XDECREF(h.ptr()); + } + + array_t(const object &o) : array(raw_array_t(o.ptr()), stolen) { + 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) { } + + explicit array_t(const std::vector<size_t> &shape, const T *ptr = nullptr, + handle base = handle()) + : array(shape, ptr, base) { } + + explicit array_t(size_t count, const T *ptr = nullptr, handle base = handle()) + : array(count, ptr, base) { } + + constexpr size_t itemsize() const { + return sizeof(T); + } + + template<typename... Ix> size_t index_at(Ix... index) const { + return offset_at(index...) / itemsize(); + } + + template<typename... Ix> const T* data(Ix... index) const { + return static_cast<const T*>(array::data(index...)); + } + + template<typename... Ix> T* mutable_data(Ix... index) { + return static_cast<T*>(array::mutable_data(index...)); + } + + // Reference to element at a given index + 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()); + } + + // 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()); + } + + /// Ensure that the argument is a NumPy array of the correct dtype. + /// In case of an error, nullptr is returned and the Python error is cleared. + static array_t ensure(handle h) { + auto result = reinterpret_steal<array_t>(raw_array_t(h.ptr())); + if (!result) + PyErr_Clear(); + return result; + } + + static bool _check(handle h) { + const auto &api = detail::npy_api::get(); + return api.PyArray_Check_(h.ptr()) + && api.PyArray_EquivTypes_(detail::array_proxy(h.ptr())->descr, dtype::of<T>().ptr()); + } + +protected: + /// Create array from any object -- always returns a new reference + static PyObject *raw_array_t(PyObject *ptr) { + if (ptr == nullptr) + return nullptr; + return detail::npy_api::get().PyArray_FromAny_( + ptr, dtype::of<T>().release().ptr(), 0, 0, + detail::npy_api::NPY_ENSURE_ARRAY_ | ExtraFlags, nullptr); + } +}; + +template <typename T> +struct format_descriptor<T, detail::enable_if_t<detail::is_pod_struct<T>::value>> { + static std::string format() { + return detail::npy_format_descriptor<typename std::remove_cv<T>::type>::format(); + } +}; + +template <size_t N> struct format_descriptor<char[N]> { + static std::string format() { return std::to_string(N) + "s"; } +}; +template <size_t N> struct format_descriptor<std::array<char, N>> { + static std::string format() { return std::to_string(N) + "s"; } +}; + +template <typename T> +struct format_descriptor<T, detail::enable_if_t<std::is_enum<T>::value>> { + static std::string format() { + return format_descriptor< + typename std::remove_cv<typename std::underlying_type<T>::type>::type>::format(); + } +}; + +NAMESPACE_BEGIN(detail) +template <typename T, int ExtraFlags> +struct pyobject_caster<array_t<T, ExtraFlags>> { + using type = array_t<T, ExtraFlags>; + + bool load(handle src, bool /* convert */) { + value = type::ensure(src); + return static_cast<bool>(value); + } + + static handle cast(const handle &src, return_value_policy /* policy */, handle /* parent */) { + return src.inc_ref(); + } + PYBIND11_TYPE_CASTER(type, handle_type_name<type>::name()); +}; + +template <typename T> struct is_std_array : std::false_type { }; +template <typename T, size_t N> struct is_std_array<std::array<T, N>> : std::true_type { }; + +template <typename T> +struct is_pod_struct { + enum { value = std::is_pod<T>::value && // offsetof only works correctly for POD types + !std::is_reference<T>::value && + !std::is_array<T>::value && + !is_std_array<T>::value && + !std::is_integral<T>::value && + !std::is_enum<T>::value && + !std::is_same<typename std::remove_cv<T>::type, float>::value && + !std::is_same<typename std::remove_cv<T>::type, double>::value && + !std::is_same<typename std::remove_cv<T>::type, bool>::value && + !std::is_same<typename std::remove_cv<T>::type, std::complex<float>>::value && + !std::is_same<typename std::remove_cv<T>::type, std::complex<double>>::value }; +}; + +template <typename T> struct npy_format_descriptor<T, enable_if_t<std::is_integral<T>::value>> { +private: + constexpr static const int values[8] = { + npy_api::NPY_BYTE_, npy_api::NPY_UBYTE_, npy_api::NPY_SHORT_, npy_api::NPY_USHORT_, + npy_api::NPY_INT_, npy_api::NPY_UINT_, npy_api::NPY_LONGLONG_, npy_api::NPY_ULONGLONG_ }; +public: + enum { value = values[detail::log2(sizeof(T)) * 2 + (std::is_unsigned<T>::value ? 1 : 0)] }; + static pybind11::dtype dtype() { + if (auto ptr = npy_api::get().PyArray_DescrFromType_(value)) + return reinterpret_borrow<pybind11::dtype>(ptr); + pybind11_fail("Unsupported buffer format!"); + } + template <typename T2 = T, enable_if_t<std::is_signed<T2>::value, int> = 0> + static PYBIND11_DESCR name() { return _("int") + _<sizeof(T)*8>(); } + template <typename T2 = T, enable_if_t<!std::is_signed<T2>::value, int> = 0> + static PYBIND11_DESCR name() { return _("uint") + _<sizeof(T)*8>(); } +}; +template <typename T> constexpr const int npy_format_descriptor< + T, enable_if_t<std::is_integral<T>::value>>::values[8]; + +#define DECL_FMT(Type, NumPyName, Name) template<> struct npy_format_descriptor<Type> { \ + enum { value = npy_api::NumPyName }; \ + static pybind11::dtype dtype() { \ + if (auto ptr = npy_api::get().PyArray_DescrFromType_(value)) \ + return reinterpret_borrow<pybind11::dtype>(ptr); \ + pybind11_fail("Unsupported buffer format!"); \ + } \ + static PYBIND11_DESCR name() { return _(Name); } } +DECL_FMT(float, NPY_FLOAT_, "float32"); +DECL_FMT(double, NPY_DOUBLE_, "float64"); +DECL_FMT(bool, NPY_BOOL_, "bool"); +DECL_FMT(std::complex<float>, NPY_CFLOAT_, "complex64"); +DECL_FMT(std::complex<double>, NPY_CDOUBLE_, "complex128"); +#undef DECL_FMT + +#define DECL_CHAR_FMT \ + static PYBIND11_DESCR name() { return _("S") + _<N>(); } \ + static pybind11::dtype dtype() { return pybind11::dtype(std::string("S") + std::to_string(N)); } +template <size_t N> struct npy_format_descriptor<char[N]> { DECL_CHAR_FMT }; +template <size_t N> struct npy_format_descriptor<std::array<char, N>> { DECL_CHAR_FMT }; +#undef DECL_CHAR_FMT + +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>; +public: + static PYBIND11_DESCR name() { return base_descr::name(); } + static pybind11::dtype dtype() { return base_descr::dtype(); } +}; + +struct field_descriptor { + const char *name; + size_t offset; + size_t size; + size_t alignment; + 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, + bool (*direct_converter)(PyObject *, void *&)) { + + auto& numpy_internals = get_numpy_internals(); + if (numpy_internals.get_type_info(tinfo, false)) + pybind11_fail("NumPy: dtype is already registered"); + + list names, formats, offsets; + for (auto field : fields) { + if (!field.descr) + pybind11_fail(std::string("NumPy: unsupported field dtype: `") + + field.name + "` @ " + tinfo.name()); + names.append(PYBIND11_STR_TYPE(field.name)); + formats.append(field.descr); + offsets.append(pybind11::int_(field.offset)); + } + auto dtype_ptr = pybind11::dtype(names, formats, offsets, itemsize).release().ptr(); + + // There is an existing bug in NumPy (as of v1.11): trailing bytes are + // not encoded explicitly into the format string. This will supposedly + // get fixed in v1.12; for further details, see these: + // - https://github.com/numpy/numpy/issues/7797 + // - https://github.com/numpy/numpy/pull/7798 + // Because of this, we won't use numpy's logic to generate buffer format + // strings and will just do it ourselves. + 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; + std::ostringstream oss; + oss << "T{"; + for (auto& field : ordered_fields) { + if (field.offset > offset) + oss << (field.offset - offset) << 'x'; + // mark unaligned fields with '=' + if (field.offset % field.alignment) + oss << '='; + oss << field.format << ':' << field.name << ':'; + offset = field.offset + field.size; + } + if (itemsize > offset) + oss << (itemsize - offset) << 'x'; + oss << '}'; + auto format_str = oss.str(); + + // Sanity check: verify that NumPy properly parses our buffer format string + auto& api = npy_api::get(); + auto arr = array(buffer_info(nullptr, itemsize, format_str, 1)); + if (!api.PyArray_EquivTypes_(dtype_ptr, arr.dtype().ptr())) + pybind11_fail("NumPy: invalid buffer descriptor!"); + + auto tindex = std::type_index(tinfo); + numpy_internals.registered_dtypes[tindex] = { dtype_ptr, format_str }; + get_internals().direct_conversions[tindex].push_back(direct_converter); +} + +template <typename T> +struct npy_format_descriptor<T, enable_if_t<is_pod_struct<T>::value>> { + static PYBIND11_DESCR name() { return _("struct"); } + + static pybind11::dtype dtype() { + return reinterpret_borrow<pybind11::dtype>(dtype_ptr()); + } + + static std::string format() { + static auto format_str = get_numpy_internals().get_type_info<T>(true)->format_str; + return format_str; + } + + static void register_dtype(const std::initializer_list<field_descriptor>& fields) { + register_structured_dtype(fields, typeid(typename std::remove_cv<T>::type), + sizeof(T), &direct_converter); + } + +private: + static PyObject* dtype_ptr() { + static PyObject* ptr = get_numpy_internals().get_type_info<T>(true)->dtype_ptr; + return ptr; + } + + static bool direct_converter(PyObject *obj, void*& value) { + auto& api = npy_api::get(); + if (!PyObject_TypeCheck(obj, api.PyVoidArrType_Type_)) + return false; + if (auto descr = reinterpret_steal<object>(api.PyArray_DescrFromScalar_(obj))) { + if (api.PyArray_EquivTypes_(dtype_ptr(), descr.ptr())) { + value = ((PyVoidScalarObject_Proxy *) obj)->obval; + return true; + } + } + return false; + } +}; + +#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() \ + } + +// Extract name, offset and format descriptor for a struct field +#define PYBIND11_FIELD_DESCRIPTOR(T, Field) PYBIND11_FIELD_DESCRIPTOR_EX(T, Field, #Field) + +// The main idea of this macro is borrowed from https://github.com/swansontec/map-macro +// (C) William Swanson, Paul Fultz +#define PYBIND11_EVAL0(...) __VA_ARGS__ +#define PYBIND11_EVAL1(...) PYBIND11_EVAL0 (PYBIND11_EVAL0 (PYBIND11_EVAL0 (__VA_ARGS__))) +#define PYBIND11_EVAL2(...) PYBIND11_EVAL1 (PYBIND11_EVAL1 (PYBIND11_EVAL1 (__VA_ARGS__))) +#define PYBIND11_EVAL3(...) PYBIND11_EVAL2 (PYBIND11_EVAL2 (PYBIND11_EVAL2 (__VA_ARGS__))) +#define PYBIND11_EVAL4(...) PYBIND11_EVAL3 (PYBIND11_EVAL3 (PYBIND11_EVAL3 (__VA_ARGS__))) +#define PYBIND11_EVAL(...) PYBIND11_EVAL4 (PYBIND11_EVAL4 (PYBIND11_EVAL4 (__VA_ARGS__))) +#define PYBIND11_MAP_END(...) +#define PYBIND11_MAP_OUT +#define PYBIND11_MAP_COMMA , +#define PYBIND11_MAP_GET_END() 0, PYBIND11_MAP_END +#define PYBIND11_MAP_NEXT0(test, next, ...) next PYBIND11_MAP_OUT +#define PYBIND11_MAP_NEXT1(test, next) PYBIND11_MAP_NEXT0 (test, next, 0) +#define PYBIND11_MAP_NEXT(test, next) PYBIND11_MAP_NEXT1 (PYBIND11_MAP_GET_END test, next) +#ifdef _MSC_VER // MSVC is not as eager to expand macros, hence this workaround +#define PYBIND11_MAP_LIST_NEXT1(test, next) \ + PYBIND11_EVAL0 (PYBIND11_MAP_NEXT0 (test, PYBIND11_MAP_COMMA next, 0)) +#else +#define PYBIND11_MAP_LIST_NEXT1(test, next) \ + PYBIND11_MAP_NEXT0 (test, PYBIND11_MAP_COMMA next, 0) +#endif +#define PYBIND11_MAP_LIST_NEXT(test, next) \ + PYBIND11_MAP_LIST_NEXT1 (PYBIND11_MAP_GET_END test, next) +#define PYBIND11_MAP_LIST0(f, t, x, peek, ...) \ + f(t, x) PYBIND11_MAP_LIST_NEXT (peek, PYBIND11_MAP_LIST1) (f, t, peek, __VA_ARGS__) +#define PYBIND11_MAP_LIST1(f, t, x, peek, ...) \ + f(t, x) PYBIND11_MAP_LIST_NEXT (peek, PYBIND11_MAP_LIST0) (f, t, peek, __VA_ARGS__) +// PYBIND11_MAP_LIST(f, t, a1, a2, ...) expands to f(t, a1), f(t, a2), ... +#define PYBIND11_MAP_LIST(f, t, ...) \ + PYBIND11_EVAL (PYBIND11_MAP_LIST1 (f, t, __VA_ARGS__, (), 0)) + +#define PYBIND11_NUMPY_DTYPE(Type, ...) \ + ::pybind11::detail::npy_format_descriptor<Type>::register_dtype \ + ({PYBIND11_MAP_LIST (PYBIND11_FIELD_DESCRIPTOR, Type, __VA_ARGS__)}) + +#ifdef _MSC_VER +#define PYBIND11_MAP2_LIST_NEXT1(test, next) \ + PYBIND11_EVAL0 (PYBIND11_MAP_NEXT0 (test, PYBIND11_MAP_COMMA next, 0)) +#else +#define PYBIND11_MAP2_LIST_NEXT1(test, next) \ + PYBIND11_MAP_NEXT0 (test, PYBIND11_MAP_COMMA next, 0) +#endif +#define PYBIND11_MAP2_LIST_NEXT(test, next) \ + PYBIND11_MAP2_LIST_NEXT1 (PYBIND11_MAP_GET_END test, next) +#define PYBIND11_MAP2_LIST0(f, t, x1, x2, peek, ...) \ + f(t, x1, x2) PYBIND11_MAP2_LIST_NEXT (peek, PYBIND11_MAP2_LIST1) (f, t, peek, __VA_ARGS__) +#define PYBIND11_MAP2_LIST1(f, t, x1, x2, peek, ...) \ + f(t, x1, x2) PYBIND11_MAP2_LIST_NEXT (peek, PYBIND11_MAP2_LIST0) (f, t, peek, __VA_ARGS__) +// PYBIND11_MAP2_LIST(f, t, a1, a2, ...) expands to f(t, a1, a2), f(t, a3, a4), ... +#define PYBIND11_MAP2_LIST(f, t, ...) \ + PYBIND11_EVAL (PYBIND11_MAP2_LIST1 (f, t, __VA_ARGS__, (), 0)) + +#define PYBIND11_NUMPY_DTYPE_EX(Type, ...) \ + ::pybind11::detail::npy_format_descriptor<Type>::register_dtype \ + ({PYBIND11_MAP2_LIST (PYBIND11_FIELD_DESCRIPTOR_EX, Type, __VA_ARGS__)}) + +template <class T> +using array_iterator = typename std::add_pointer<T>::type; + +template <class T> +array_iterator<T> array_begin(const buffer_info& buffer) { + return array_iterator<T>(reinterpret_cast<T*>(buffer.ptr)); +} + +template <class T> +array_iterator<T> array_end(const buffer_info& buffer) { + return array_iterator<T>(reinterpret_cast<T*>(buffer.ptr) + buffer.size); +} + +class common_iterator { +public: + using container_type = std::vector<size_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) + : 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) { + size_type j = i - 1; + value_type s = static_cast<value_type>(shape[i]); + m_strides[j] = strides[j] + m_strides[i] - strides[i] * s; + } + } + + void increment(size_type dim) { + p_ptr += m_strides[dim]; + } + + void* data() const { + return p_ptr; + } + +private: + char* p_ptr; + container_type m_strides; +}; + +template <size_t N> class multi_array_iterator { +public: + using container_type = std::vector<size_t>; + + multi_array_iterator(const std::array<buffer_info, N> &buffers, + const std::vector<size_t> &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]); + + container_type strides(shape.size()); + for (size_t i = 0; i < N; ++i) + init_common_iterator(buffers[i], shape, m_common_iterator[i], strides); + } + + multi_array_iterator& operator++() { + for (size_t j = m_index.size(); j != 0; --j) { + size_t i = j - 1; + if (++m_index[i] != m_shape[i]) { + increment_common_iterator(i); + break; + } else { + m_index[i] = 0; + } + } + return *this; + } + + template <size_t K, class T> const T& data() const { + return *reinterpret_cast<T*>(m_common_iterator[K].data()); + } + +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) { + auto buffer_shape_iter = buffer.shape.rbegin(); + auto buffer_strides_iter = buffer.strides.rbegin(); + auto shape_iter = shape.rbegin(); + auto strides_iter = strides.rbegin(); + + while (buffer_shape_iter != buffer.shape.rend()) { + if (*shape_iter == *buffer_shape_iter) + *strides_iter = static_cast<size_t>(*buffer_strides_iter); + else + *strides_iter = 0; + + ++buffer_shape_iter; + ++buffer_strides_iter; + ++shape_iter; + ++strides_iter; + } + + std::fill(strides_iter, strides.rend(), 0); + iterator = common_iter(buffer.ptr, strides, shape); + } + + void increment_common_iterator(size_t dim) { + for (auto &iter : m_common_iterator) + iter.increment(dim); + } + + container_type m_shape; + container_type m_index; + std::array<common_iter, N> m_common_iterator; +}; + +template <size_t N> +bool 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) { + return std::max(res, buf.ndim); + }); + + shape = std::vector<size_t>(ndim, 1); + bool trivial_broadcast = true; + for (size_t i = 0; i < N; ++i) { + auto res_iter = shape.rbegin(); + bool i_trivial_broadcast = (buffers[i].size == 1) || (buffers[i].ndim == ndim); + for (auto shape_iter = buffers[i].shape.rbegin(); + shape_iter != buffers[i].shape.rend(); ++shape_iter, ++res_iter) { + + if (*res_iter == 1) + *res_iter = *shape_iter; + else if ((*shape_iter != 1) && (*res_iter != *shape_iter)) + pybind11_fail("pybind11::vectorize: incompatible size/dimension of inputs!"); + + i_trivial_broadcast = i_trivial_broadcast && (*res_iter == *shape_iter); + } + trivial_broadcast = trivial_broadcast && i_trivial_broadcast; + } + return trivial_broadcast; +} + +template <typename Func, typename Return, typename... Args> +struct vectorize_helper { + typename std::remove_reference<Func>::type f; + + template <typename T> + explicit vectorize_helper(T&&f) : f(std::forward<T>(f)) { } + + object operator()(array_t<Args, array::c_style | array::forcecast>... args) { + return run(args..., make_index_sequence<sizeof...(Args)>()); + } + + template <size_t ... Index> object run(array_t<Args, array::c_style | array::forcecast>&... args, index_sequence<Index...> index) { + /* Request buffers from all parameters */ + const size_t N = sizeof...(Args); + + std::array<buffer_info, N> buffers {{ args.request()... }}; + + /* Determine dimensions parameters of output array */ + size_t ndim = 0; + std::vector<size_t> shape(0); + bool trivial_broadcast = broadcast(buffers, ndim, shape); + + size_t size = 1; + std::vector<size_t> strides(ndim); + if (ndim > 0) { + 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]; + } + + if (size == 1) + return cast(f(*((Args *) buffers[Index].ptr)...)); + + array_t<Return> result(shape, strides); + auto buf = result.request(); + auto output = (Return *) buf.ptr; + + if (trivial_broadcast) { + /* Call the function */ + for (size_t i = 0; i < size; ++i) { + output[i] = f((buffers[Index].size == 1 + ? *((Args *) buffers[Index].ptr) + : ((Args *) buffers[Index].ptr)[i])...); + } + } else { + apply_broadcast<N, Index...>(buffers, buf, index); + } + + return result; + } + + template <size_t N, 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>; + + input_iterator input_iter(buffers, output.shape); + output_iterator output_end = array_end<Return>(output); + + for (output_iterator iter = array_begin<Return>(output); + iter != output_end; ++iter, ++input_iter) { + *iter = f((input_iter.template data<Index, Args>())...); + } + } +}; + +template <typename T, int Flags> struct handle_type_name<array_t<T, Flags>> { + static PYBIND11_DESCR name() { return _("numpy.ndarray[") + type_caster<T>::name() + _("]"); } +}; + +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); +} + +template <typename Return, typename... Args> +detail::vectorize_helper<Return (*) (Args ...), Return, Args...> vectorize(Return (*f) (Args ...)) { + return vectorize<Return (*) (Args ...), Return, Args...>(f, f); +} + +template <typename Func> +auto vectorize(Func &&f) -> decltype( + vectorize(std::forward<Func>(f), (typename detail::remove_class<decltype(&std::remove_reference<Func>::type::operator())>::type *) nullptr)) { + return vectorize(std::forward<Func>(f), (typename detail::remove_class<decltype( + &std::remove_reference<Func>::type::operator())>::type *) nullptr); +} + +NAMESPACE_END(pybind11) + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif diff --git a/ext/pybind11/include/pybind11/operators.h b/ext/pybind11/include/pybind11/operators.h new file mode 100644 index 000000000..2e78c01a3 --- /dev/null +++ b/ext/pybind11/include/pybind11/operators.h @@ -0,0 +1,154 @@ +/* + pybind11/operator.h: Metatemplates for operator overloading + + 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 "pybind11.h" + +#if defined(__clang__) && !defined(__INTEL_COMPILER) +# pragma clang diagnostic ignored "-Wunsequenced" // multiple unsequenced modifications to 'self' (when using def(py::self OP Type())) +#endif + +NAMESPACE_BEGIN(pybind11) +NAMESPACE_BEGIN(detail) + +/// Enumeration with all supported operator types +enum op_id : int { + op_add, op_sub, op_mul, op_div, op_mod, op_divmod, op_pow, op_lshift, + op_rshift, op_and, op_xor, op_or, op_neg, op_pos, op_abs, op_invert, + 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 +}; + +enum op_type : int { + op_l, /* base type on left */ + op_r, /* base type on right */ + op_u /* unary operator */ +}; + +struct self_t { }; +static const self_t self = self_t(); + +/// Type for an unused type slot +struct undefined_t { }; + +/// Don't warn about an unused variable +inline self_t __self() { return self; } + +/// base template of operator implementations +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; + cl.def(op::name(), &op::execute, is_operator(), extra...); + } + 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; + cl.def(op::name(), &op::execute_cast, is_operator(), extra...); + } +}; + +#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); } \ + static B execute_cast(const L &l, const R &r) { return B(expr); } \ +}; \ +template <typename B, typename L, typename R> struct op_impl<op_##id, op_r, B, L, R> { \ + static char const* name() { return "__" #rid "__"; } \ + static auto execute(const R &r, const L &l) -> decltype(expr) { return (expr); } \ + static B execute_cast(const R &r, const L &l) { return B(expr); } \ +}; \ +inline op_<op_##id, op_l, self_t, self_t> op(const self_t &, const self_t &) { \ + return op_<op_##id, op_l, self_t, self_t>(); \ +} \ +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>(); \ +} \ +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) \ +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; } \ + static B execute_cast(L &l, const R &r) { return B(expr); } \ +}; \ +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) \ +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; } \ + static B execute_cast(const L &l) { return B(expr); } \ +}; \ +inline op_<op_##id, op_u, self_t, undefined_t> op(const self_t &) { \ + return op_<op_##id, op_u, self_t, undefined_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) +PYBIND11_BINARY_OPERATOR(and, rand, operator&, l & r) +PYBIND11_BINARY_OPERATOR(xor, rxor, operator^, l ^ r) +PYBIND11_BINARY_OPERATOR(eq, eq, operator==, l == r) +PYBIND11_BINARY_OPERATOR(ne, ne, operator!=, l != r) +PYBIND11_BINARY_OPERATOR(or, ror, operator|, l | r) +PYBIND11_BINARY_OPERATOR(gt, lt, operator>, l > r) +PYBIND11_BINARY_OPERATOR(ge, le, operator>=, l >= r) +PYBIND11_BINARY_OPERATOR(lt, gt, operator<, l < r) +PYBIND11_BINARY_OPERATOR(le, ge, operator<=, l <= r) +//PYBIND11_BINARY_OPERATOR(pow, rpow, pow, std::pow(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(imod, operator%=, l %= r) +PYBIND11_INPLACE_OPERATOR(ilshift, operator<<=, l <<= r) +PYBIND11_INPLACE_OPERATOR(irshift, operator>>=, l >>= r) +PYBIND11_INPLACE_OPERATOR(iand, operator&=, l &= r) +PYBIND11_INPLACE_OPERATOR(ixor, operator^=, l ^= r) +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(invert, operator~, (~l)) +PYBIND11_UNARY_OPERATOR(bool, operator!, !!l) +PYBIND11_UNARY_OPERATOR(int, int_, (int) l) +PYBIND11_UNARY_OPERATOR(float, float_, (double) l) + +#undef PYBIND11_BINARY_OPERATOR +#undef PYBIND11_INPLACE_OPERATOR +#undef PYBIND11_UNARY_OPERATOR +NAMESPACE_END(detail) + +using detail::self; + +NAMESPACE_END(pybind11) diff --git a/ext/pybind11/include/pybind11/options.h b/ext/pybind11/include/pybind11/options.h new file mode 100644 index 000000000..3105551dd --- /dev/null +++ b/ext/pybind11/include/pybind11/options.h @@ -0,0 +1,65 @@ +/* + pybind11/options.h: global settings that are configurable at runtime. + + 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 "common.h" + +NAMESPACE_BEGIN(pybind11) + +class options { +public: + + // Default RAII constructor, which leaves settings as they currently are. + options() : previous_state(global_state()) {} + + // Class is non-copyable. + options(const options&) = delete; + options& operator=(const options&) = delete; + + // Destructor, which restores settings that were in effect before. + ~options() { + global_state() = previous_state; + } + + // Setter methods (affect the global state): + + options& disable_user_defined_docstrings() & { global_state().show_user_defined_docstrings = false; return *this; } + + options& enable_user_defined_docstrings() & { global_state().show_user_defined_docstrings = true; return *this; } + + options& disable_function_signatures() & { global_state().show_function_signatures = false; return *this; } + + options& enable_function_signatures() & { global_state().show_function_signatures = true; return *this; } + + // Getter methods (return the global state): + + static bool show_user_defined_docstrings() { return global_state().show_user_defined_docstrings; } + + static bool show_function_signatures() { return global_state().show_function_signatures; } + + // This type is not meant to be allocated on the heap. + void* operator new(size_t) = delete; + +private: + + struct state { + bool show_user_defined_docstrings = true; //< Include user-supplied texts in docstrings. + bool show_function_signatures = true; //< Include auto-generated function signatures in docstrings. + }; + + static state &global_state() { + static state instance; + return instance; + } + + state previous_state; +}; + +NAMESPACE_END(pybind11) diff --git a/ext/pybind11/include/pybind11/pybind11.h b/ext/pybind11/include/pybind11/pybind11.h new file mode 100644 index 000000000..1db9efb8c --- /dev/null +++ b/ext/pybind11/include/pybind11/pybind11.h @@ -0,0 +1,1735 @@ +/* + pybind11/pybind11.h: Main header file of the C++11 python + binding generator library + + 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(_MSC_VER) +# pragma warning(push) +# pragma warning(disable: 4100) // warning C4100: Unreferenced formal parameter +# pragma warning(disable: 4127) // warning C4127: Conditional expression is constant +# pragma warning(disable: 4512) // warning C4512: Assignment operator was implicitly defined as deleted +# pragma warning(disable: 4800) // warning C4800: 'int': forcing value to bool 'true' or 'false' (performance warning) +# pragma warning(disable: 4996) // warning C4996: The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name +# pragma warning(disable: 4702) // warning C4702: unreachable code +# pragma warning(disable: 4522) // warning C4522: multiple assignment operators specified +#elif defined(__INTEL_COMPILER) +# pragma warning(push) +# pragma warning(disable: 186) // pointless comparison of unsigned integer with zero +# pragma warning(disable: 1334) // the "template" keyword used for syntactic disambiguation may only be used within a template +# pragma warning(disable: 2196) // warning #2196: routine is both "inline" and "noinline" +#elif defined(__GNUG__) && !defined(__clang__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wunused-but-set-parameter" +# pragma GCC diagnostic ignored "-Wunused-but-set-variable" +# pragma GCC diagnostic ignored "-Wmissing-field-initializers" +# pragma GCC diagnostic ignored "-Wstrict-aliasing" +# pragma GCC diagnostic ignored "-Wattributes" +#endif + +#include "attr.h" +#include "options.h" + +NAMESPACE_BEGIN(pybind11) + +/// Wraps an arbitrary C++ function/method/lambda function/.. into a callable Python object +class cpp_function : public function { +public: + cpp_function() { } + + /// Construct a cpp_function from a vanilla function pointer + template <typename Return, typename... Args, typename... Extra> + cpp_function(Return (*f)(Args...), const Extra&... extra) { + initialize(f, f, extra...); + } + + /// Construct a cpp_function from a lambda function (possibly with internal state) + template <typename Func, typename... Extra> cpp_function(Func &&f, const Extra&... extra) { + initialize(std::forward<Func>(f), + (typename detail::remove_class<decltype( + &std::remove_reference<Func>::type::operator())>::type *) nullptr, extra...); + } + + /// Construct a cpp_function from a class method (non-const) + template <typename Return, typename Class, typename... Arg, typename... Extra> + cpp_function(Return (Class::*f)(Arg...), const Extra&... extra) { + initialize([f](Class *c, Arg... args) -> Return { return (c->*f)(args...); }, + (Return (*) (Class *, Arg...)) nullptr, extra...); + } + + /// Construct a cpp_function from a class method (const) + template <typename Return, typename Class, typename... Arg, typename... Extra> + cpp_function(Return (Class::*f)(Arg...) const, const Extra&... extra) { + initialize([f](const Class *c, Arg... args) -> Return { return (c->*f)(args...); }, + (Return (*)(const Class *, Arg ...)) nullptr, extra...); + } + + /// Return the function name + object name() const { return attr("__name__"); } + +protected: + /// Space optimization: don't inline this frequently instantiated fragment + PYBIND11_NOINLINE detail::function_record *make_function_record() { + return new detail::function_record(); + } + + /// Special internal constructor for functors, lambda functions, etc. + template <typename Func, typename Return, typename... Args, typename... Extra> + void initialize(Func &&f, Return (*)(Args...), const Extra&... extra) { + static_assert(detail::expected_num_args<Extra...>(sizeof...(Args)), + "The number of named arguments does not match the function signature"); + + struct capture { typename std::remove_reference<Func>::type f; }; + + /* Store the function including any extra state it might have (e.g. a lambda capture object) */ + auto rec = make_function_record(); + + /* Store the capture object directly in the function record if there is enough space */ + if (sizeof(capture) <= sizeof(rec->data)) { + /* Without these pragmas, GCC warns that there might not be + enough space to use the placement new operator. However, the + 'if' statement above ensures that this is the case. */ +#if defined(__GNUG__) && !defined(__clang__) && __GNUC__ >= 6 +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wplacement-new" +#endif + new ((capture *) &rec->data) capture { std::forward<Func>(f) }; +#if defined(__GNUG__) && !defined(__clang__) && __GNUC__ >= 6 +# pragma GCC diagnostic pop +#endif + if (!std::is_trivially_destructible<Func>::value) + rec->free_data = [](detail::function_record *r) { ((capture *) &r->data)->~capture(); }; + } else { + rec->data[0] = new capture { std::forward<Func>(f) }; + rec->free_data = [](detail::function_record *r) { delete ((capture *) r->data[0]); }; + } + + /* Type casters for the function arguments and return value */ + using cast_in = detail::argument_loader<Args...>; + using cast_out = detail::make_caster< + detail::conditional_t<std::is_void<Return>::value, detail::void_type, Return> + >; + + /* Dispatch code which converts function arguments and performs the actual function call */ + rec->impl = [](detail::function_record *rec, handle args, handle kwargs, handle parent) -> handle { + cast_in args_converter; + + /* Try to cast the function arguments into the C++ domain */ + if (!args_converter.load_args(args, kwargs, true)) + return PYBIND11_TRY_NEXT_OVERLOAD; + + /* Invoke call policy pre-call hook */ + detail::process_attributes<Extra...>::precall(args); + + /* Get a pointer to the capture object */ + capture *cap = (capture *) (sizeof(capture) <= sizeof(rec->data) + ? &rec->data : rec->data[0]); + + /* Override policy for rvalues -- always move */ + constexpr auto is_rvalue = !std::is_pointer<Return>::value + && !std::is_lvalue_reference<Return>::value; + const auto policy = is_rvalue ? return_value_policy::move : rec->policy; + + /* Perform the function call */ + handle result = cast_out::cast(args_converter.template call<Return>(cap->f), + policy, parent); + + /* Invoke call policy post-call hook */ + detail::process_attributes<Extra...>::postcall(args, result); + + return result; + }; + + /* Process any user-provided function attributes */ + detail::process_attributes<Extra...>::init(extra..., rec); + + /* Generate a readable signature describing the function's arguments and return value types */ + using detail::descr; using detail::_; + PYBIND11_DESCR signature = _("(") + cast_in::arg_names() + _(") -> ") + cast_out::name(); + + /* Register the function with Python from generic (non-templated) code */ + initialize_generic(rec, signature.text(), signature.types(), sizeof...(Args)); + + if (cast_in::has_args) rec->has_args = true; + if (cast_in::has_kwargs) rec->has_kwargs = true; + + /* Stash some additional information used by an important optimization in 'functional.h' */ + using FunctionType = Return (*)(Args...); + constexpr bool is_function_ptr = + std::is_convertible<Func, FunctionType>::value && + sizeof(capture) == sizeof(void *); + if (is_function_ptr) { + rec->is_stateless = true; + rec->data[1] = (void *) &typeid(FunctionType); + } + } + + /// Register a function call with Python (generic non-templated code goes here) + void initialize_generic(detail::function_record *rec, const char *text, + const std::type_info *const *types, size_t args) { + + /* Create copies of all referenced C-style strings */ + rec->name = strdup(rec->name ? rec->name : ""); + if (rec->doc) rec->doc = strdup(rec->doc); + for (auto &a: rec->args) { + if (a.name) + a.name = strdup(a.name); + if (a.descr) + a.descr = strdup(a.descr); + else if (a.value) + a.descr = strdup(a.value.attr("__repr__")().cast<std::string>().c_str()); + } + + /* Generate a proper function signature */ + std::string signature; + size_t type_depth = 0, char_index = 0, type_index = 0, arg_index = 0; + while (true) { + char c = text[char_index++]; + if (c == '\0') + break; + + if (c == '{') { + // Write arg name for everything except *args, **kwargs and return type. + if (type_depth == 0 && text[char_index] != '*' && arg_index < args) { + if (!rec->args.empty()) { + signature += rec->args[arg_index].name; + } else if (arg_index == 0 && rec->is_method) { + signature += "self"; + } else { + signature += "arg" + std::to_string(arg_index - (rec->is_method ? 1 : 0)); + } + signature += ": "; + } + ++type_depth; + } else if (c == '}') { + --type_depth; + if (type_depth == 0) { + if (arg_index < rec->args.size() && rec->args[arg_index].descr) { + signature += "="; + signature += rec->args[arg_index].descr; + } + arg_index++; + } + } else if (c == '%') { + const std::type_info *t = types[type_index++]; + if (!t) + pybind11_fail("Internal error while parsing type signature (1)"); + if (auto tinfo = detail::get_type_info(*t)) { + signature += tinfo->type->tp_name; + } else { + std::string tname(t->name()); + detail::clean_type_id(tname); + signature += tname; + } + } else { + signature += c; + } + } + if (type_depth != 0 || types[type_index] != nullptr) + pybind11_fail("Internal error while parsing type signature (2)"); + + #if !defined(PYBIND11_CPP14) + delete[] types; + delete[] text; + #endif + +#if PY_MAJOR_VERSION < 3 + if (strcmp(rec->name, "__next__") == 0) { + std::free(rec->name); + rec->name = strdup("next"); + } else if (strcmp(rec->name, "__bool__") == 0) { + std::free(rec->name); + rec->name = strdup("__nonzero__"); + } +#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 = (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 + + detail::function_record *chain = nullptr, *chain_start = rec; + if (rec->sibling) { + if (PyCFunction_Check(rec->sibling.ptr())) { + auto rec_capsule = reinterpret_borrow<capsule>(PyCFunction_GetSelf(rec->sibling.ptr())); + 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) + chain = nullptr; + } + // Don't trigger for things like the default __init__, which are wrapper_descriptors that we are intentionally replacing + else if (!rec->sibling.is_none() && rec->name[0] != '_') + pybind11_fail("Cannot overload existing non-function object \"" + std::string(rec->name) + + "\" with a function of the same name"); + } + + if (!chain) { + /* No existing overload was found, create a new function object */ + rec->def = new PyMethodDef(); + 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; + + capsule rec_capsule(rec, [](PyObject *o) { + destruct((detail::function_record *) PyCapsule_GetPointer(o, nullptr)); + }); + + object scope_module; + if (rec->scope) { + if (hasattr(rec->scope, "__module__")) { + scope_module = rec->scope.attr("__module__"); + } else if (hasattr(rec->scope, "__name__")) { + scope_module = rec->scope.attr("__name__"); + } + } + + m_ptr = PyCFunction_NewEx(rec->def, rec_capsule.ptr(), scope_module.ptr()); + if (!m_ptr) + pybind11_fail("cpp_function::cpp_function(): Could not allocate function object"); + } else { + /* Append at the end of the overload chain */ + m_ptr = rec->sibling.ptr(); + inc_ref(); + chain_start = chain; + while (chain->next) + chain = chain->next; + chain->next = rec; + } + + std::string signatures; + int index = 0; + /* Create a nice pydoc rec including all signatures and + docstrings of the functions in the overload chain */ + if (chain && options::show_function_signatures()) { + // First a generic signature + signatures += rec->name; + signatures += "(*args, **kwargs)\n"; + signatures += "Overloaded function.\n\n"; + } + // Then specific overload signatures + for (auto it = chain_start; it != nullptr; it = it->next) { + if (options::show_function_signatures()) { + if (chain) + signatures += std::to_string(++index) + ". "; + signatures += rec->name; + signatures += it->signature; + signatures += "\n"; + } + if (it->doc && strlen(it->doc) > 0 && options::show_user_defined_docstrings()) { + if (options::show_function_signatures()) signatures += "\n"; + signatures += it->doc; + if (options::show_function_signatures()) signatures += "\n"; + } + if (it->next) + signatures += "\n"; + } + + /* Install docstring */ + PyCFunctionObject *func = (PyCFunctionObject *) m_ptr; + if (func->m_ml->ml_doc) + std::free((char *) func->m_ml->ml_doc); + func->m_ml->ml_doc = strdup(signatures.c_str()); + + if (rec->is_method) { + m_ptr = PYBIND11_INSTANCE_METHOD_NEW(m_ptr, rec->scope.ptr()); + if (!m_ptr) + pybind11_fail("cpp_function::cpp_function(): Could not allocate instance method object"); + Py_DECREF(func); + } + } + + /// When a cpp_function is GCed, release any memory allocated by pybind11 + static void destruct(detail::function_record *rec) { + while (rec) { + detail::function_record *next = rec->next; + if (rec->free_data) + rec->free_data(rec); + std::free((char *) rec->name); + std::free((char *) rec->doc); + std::free((char *) rec->signature); + for (auto &arg: rec->args) { + std::free((char *) arg.name); + std::free((char *) arg.descr); + arg.value.dec_ref(); + } + if (rec->def) { + std::free((char *) rec->def->ml_doc); + delete rec->def; + } + delete rec; + rec = next; + } + } + + /// Main dispatch logic for calls to functions bound using pybind11 + static PyObject *dispatcher(PyObject *self, PyObject *args, PyObject *kwargs) { + /* Iterator over the list of potentially admissible overloads */ + detail::function_record *overloads = (detail::function_record *) PyCapsule_GetPointer(self, nullptr), + *it = overloads; + + /* Need to know how many arguments + keyword arguments there are to pick the right overload */ + size_t nargs = (size_t) PyTuple_GET_SIZE(args), + nkwargs = kwargs ? (size_t) PyDict_Size(kwargs) : 0; + + handle parent = nargs > 0 ? PyTuple_GET_ITEM(args, 0) : nullptr, + result = PYBIND11_TRY_NEXT_OVERLOAD; + try { + for (; it != nullptr; it = it->next) { + auto args_ = reinterpret_borrow<tuple>(args); + size_t kwargs_consumed = 0; + + /* For each overload: + 1. If the required list of arguments is longer than the + actually provided amount, create a copy of the argument + list and fill in any available keyword/default arguments. + 2. Ensure that all keyword arguments were "consumed" + 3. Call the function call dispatcher (function_record::impl) + */ + size_t nargs_ = nargs; + if (nargs < it->args.size()) { + nargs_ = it->args.size(); + args_ = tuple(nargs_); + for (size_t i = 0; i < nargs; ++i) { + handle item = PyTuple_GET_ITEM(args, i); + PyTuple_SET_ITEM(args_.ptr(), i, item.inc_ref().ptr()); + } + + int arg_ctr = 0; + for (auto const &it2 : it->args) { + int index = arg_ctr++; + if (PyTuple_GET_ITEM(args_.ptr(), index)) + continue; + + handle value; + if (kwargs) + value = PyDict_GetItemString(kwargs, it2.name); + + if (value) + kwargs_consumed++; + else if (it2.value) + value = it2.value; + + if (value) { + PyTuple_SET_ITEM(args_.ptr(), index, value.inc_ref().ptr()); + } else { + kwargs_consumed = (size_t) -1; /* definite failure */ + break; + } + } + } + + try { + if ((kwargs_consumed == nkwargs || it->has_kwargs) && + (nargs_ == it->nargs || it->has_args)) + result = it->impl(it, args_, kwargs, parent); + } catch (reference_cast_error &) { + result = PYBIND11_TRY_NEXT_OVERLOAD; + } + + if (result.ptr() != PYBIND11_TRY_NEXT_OVERLOAD) + break; + } + } catch (error_already_set &e) { + e.restore(); + return nullptr; + } catch (...) { + /* When an exception is caught, give each registered exception + translator a chance to translate it to a Python exception + in reverse order of registration. + + A translator may choose to do one of the following: + + - catch the exception and call PyErr_SetString or PyErr_SetObject + to set a standard (or custom) Python exception, or + - do nothing and let the exception fall through to the next translator, or + - delegate translation to the next translator by throwing a new type of exception. */ + + auto last_exception = std::current_exception(); + auto ®istered_exception_translators = pybind11::detail::get_internals().registered_exception_translators; + for (auto& translator : registered_exception_translators) { + try { + translator(last_exception); + } catch (...) { + last_exception = std::current_exception(); + continue; + } + return nullptr; + } + PyErr_SetString(PyExc_SystemError, "Exception escaped from default exception translator!"); + return nullptr; + } + + if (result.ptr() == PYBIND11_TRY_NEXT_OVERLOAD) { + if (overloads->is_operator) + return handle(Py_NotImplemented).inc_ref().ptr(); + + std::string msg = std::string(overloads->name) + "(): incompatible " + + std::string(overloads->is_constructor ? "constructor" : "function") + + " arguments. The following argument types are supported:\n"; + + int ctr = 0; + for (detail::function_record *it2 = overloads; it2 != nullptr; it2 = it2->next) { + msg += " "+ std::to_string(++ctr) + ". "; + + bool wrote_sig = false; + if (overloads->is_constructor) { + // For a constructor, rewrite `(self: Object, arg0, ...) -> NoneType` as `Object(arg0, ...)` + std::string sig = it2->signature; + size_t start = sig.find('(') + 7; // skip "(self: " + if (start < sig.size()) { + // End at the , for the next argument + size_t end = sig.find(", "), next = end + 2; + size_t ret = sig.rfind(" -> "); + // Or the ), if there is no comma: + if (end >= sig.size()) next = end = sig.find(')'); + if (start < end && next < sig.size()) { + msg.append(sig, start, end - start); + msg += '('; + msg.append(sig, next, ret - next); + wrote_sig = true; + } + } + } + if (!wrote_sig) msg += it2->signature; + + msg += "\n"; + } + msg += "\nInvoked with: "; + auto args_ = reinterpret_borrow<tuple>(args); + for (size_t ti = overloads->is_constructor ? 1 : 0; ti < args_.size(); ++ti) { + msg += pybind11::repr(args_[ti]); + if ((ti + 1) != args_.size() ) + 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; + 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. */ + PyObject *inst = PyTuple_GET_ITEM(args, 0); + auto tinfo = detail::get_type_info(Py_TYPE(inst)); + tinfo->init_holder(inst, nullptr); + } + return result.ptr(); + } + } +}; + +/// Wrapper for Python extension modules +class module : public object { +public: + PYBIND11_OBJECT_DEFAULT(module, object, PyModule_Check) + + explicit module(const char *name, const char *doc = nullptr) { + if (!options::show_user_defined_docstrings()) doc = nullptr; +#if PY_MAJOR_VERSION >= 3 + PyModuleDef *def = new PyModuleDef(); + memset(def, 0, sizeof(PyModuleDef)); + def->m_name = name; + def->m_doc = doc; + def->m_size = -1; + Py_INCREF(def); + m_ptr = PyModule_Create(def); +#else + m_ptr = Py_InitModule3(name, nullptr, doc); +#endif + if (m_ptr == nullptr) + pybind11_fail("Internal error in module::module()"); + inc_ref(); + } + + template <typename Func, typename... Extra> + module &def(const char *name_, Func &&f, const Extra& ... extra) { + cpp_function func(std::forward<Func>(f), name(name_), scope(*this), + sibling(getattr(*this, name_, none())), extra...); + // NB: allow overwriting here because cpp_function sets up a chain with the intention of + // overwriting (and has already checked internally that it isn't overwriting non-functions). + add_object(name_, func, true /* overwrite */); + return *this; + } + + module def_submodule(const char *name, const char *doc = nullptr) { + std::string full_name = std::string(PyModule_GetName(m_ptr)) + + std::string(".") + std::string(name); + auto result = reinterpret_borrow<module>(PyImport_AddModule(full_name.c_str())); + if (doc && options::show_user_defined_docstrings()) + result.attr("__doc__") = pybind11::str(doc); + attr(name) = result; + return result; + } + + static module import(const char *name) { + PyObject *obj = PyImport_ImportModule(name); + if (!obj) + throw error_already_set(); + return 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) { + 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()); + } +}; + +NAMESPACE_BEGIN(detail) +extern "C" inline PyObject *get_dict(PyObject *op, void *) { + PyObject *&dict = *_PyObject_GetDictPtr(op); + if (!dict) { + dict = PyDict_New(); + } + Py_XINCREF(dict); + return dict; +} + +extern "C" inline int set_dict(PyObject *op, PyObject *new_dict, void *) { + if (!PyDict_Check(new_dict)) { + PyErr_Format(PyExc_TypeError, "__dict__ must be set to a dictionary, not a '%.200s'", + Py_TYPE(new_dict)->tp_name); + return -1; + } + PyObject *&dict = *_PyObject_GetDictPtr(op); + Py_INCREF(new_dict); + Py_CLEAR(dict); + dict = new_dict; + return 0; +} + +static PyGetSetDef generic_getset[] = { + {const_cast<char*>("__dict__"), get_dict, set_dict, nullptr, nullptr}, + {nullptr, nullptr, nullptr, nullptr, nullptr} +}; + +/// Generic support for creating new Python heap types +class generic_type : public object { + template <typename...> friend class class_; +public: + PYBIND11_OBJECT_DEFAULT(generic_type, object, PyType_Check) +protected: + void initialize(type_record *rec) { + auto &internals = get_internals(); + auto tindex = std::type_index(*(rec->type)); + + if (get_type_info(*(rec->type))) + pybind11_fail("generic_type: type \"" + std::string(rec->name) + + "\" is already registered!"); + + auto name = reinterpret_steal<object>(PYBIND11_FROM_STRING(rec->name)); + object scope_module; + if (rec->scope) { + if (hasattr(rec->scope, rec->name)) + pybind11_fail("generic_type: cannot initialize type \"" + std::string(rec->name) + + "\": an object with that name is already defined"); + + if (hasattr(rec->scope, "__module__")) { + scope_module = rec->scope.attr("__module__"); + } else if (hasattr(rec->scope, "__name__")) { + scope_module = rec->scope.attr("__name__"); + } + } + +#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 + /* Qualified names for Python >= 3.3 */ + object scope_qualname; + if (rec->scope && hasattr(rec->scope, "__qualname__")) + scope_qualname = rec->scope.attr("__qualname__"); + object ht_qualname; + if (scope_qualname) { + ht_qualname = reinterpret_steal<object>(PyUnicode_FromFormat( + "%U.%U", scope_qualname.ptr(), name.ptr())); + } else { + ht_qualname = name; + } +#endif + + size_t num_bases = rec->bases.size(); + auto bases = tuple(rec->bases); + + std::string full_name = (scope_module ? ((std::string) pybind11::str(scope_module) + "." + rec->name) + : std::string(rec->name)); + + char *tp_doc = nullptr; + if (rec->doc && options::show_user_defined_docstrings()) { + /* Allocate memory for docstring (using PyObject_MALLOC, since + Python will free this later on) */ + size_t size = strlen(rec->doc) + 1; + tp_doc = (char *) PyObject_MALLOC(size); + memcpy((void *) tp_doc, rec->doc, size); + } + + /* 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 type_holder = reinterpret_steal<object>(PyType_Type.tp_alloc(&PyType_Type, 0)); + auto type = (PyHeapTypeObject*) type_holder.ptr(); + + if (!type_holder || !name) + pybind11_fail(std::string(rec->name) + ": Unable to create type object!"); + + /* Register supplemental type information in C++ dict */ + detail::type_info *tinfo = new detail::type_info(); + tinfo->type = (PyTypeObject *) type; + tinfo->type_size = rec->type_size; + tinfo->init_holder = rec->init_holder; + tinfo->direct_conversions = &internals.direct_conversions[tindex]; + internals.registered_types_cpp[tindex] = tinfo; + internals.registered_types_py[type] = tinfo; + + /* Basic type attributes */ + type->ht_type.tp_name = strdup(full_name.c_str()); + type->ht_type.tp_basicsize = (ssize_t) rec->instance_size; + + if (num_bases > 0) { + type->ht_type.tp_base = (PyTypeObject *) ((object) bases[0]).inc_ref().ptr(); + type->ht_type.tp_bases = bases.release().ptr(); + rec->multiple_inheritance |= num_bases > 1; + } + + type->ht_name = name.release().ptr(); + +#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 + type->ht_qualname = ht_qualname.release().ptr(); +#endif + + /* Supported protocols */ + type->ht_type.tp_as_number = &type->as_number; + type->ht_type.tp_as_sequence = &type->as_sequence; + type->ht_type.tp_as_mapping = &type->as_mapping; + + /* Supported elementary operations */ + type->ht_type.tp_init = (initproc) init; + type->ht_type.tp_new = (newfunc) new_instance; + type->ht_type.tp_dealloc = rec->dealloc; + + /* Support weak references (needed for the keep_alive feature) */ + type->ht_type.tp_weaklistoffset = offsetof(instance_essentials<void>, weakrefs); + + /* Flags */ + type->ht_type.tp_flags |= Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE; +#if PY_MAJOR_VERSION < 3 + type->ht_type.tp_flags |= Py_TPFLAGS_CHECKTYPES; +#endif + type->ht_type.tp_flags &= ~Py_TPFLAGS_HAVE_GC; + + /* Support dynamic attributes */ + if (rec->dynamic_attr) { + type->ht_type.tp_flags |= Py_TPFLAGS_HAVE_GC; + type->ht_type.tp_dictoffset = type->ht_type.tp_basicsize; // place the dict at the end + type->ht_type.tp_basicsize += sizeof(PyObject *); // and allocate enough space for it + type->ht_type.tp_getset = generic_getset; + type->ht_type.tp_traverse = traverse; + type->ht_type.tp_clear = clear; + } + + type->ht_type.tp_doc = tp_doc; + + if (PyType_Ready(&type->ht_type) < 0) + pybind11_fail(std::string(rec->name) + ": PyType_Ready failed (" + + detail::error_string() + ")!"); + + m_ptr = type_holder.ptr(); + + if (scope_module) // Needed by pydoc + attr("__module__") = scope_module; + + /* Register type with the parent scope */ + if (rec->scope) + rec->scope.attr(handle(type->ht_name)) = *this; + + if (rec->multiple_inheritance) + mark_parents_nonsimple(&type->ht_type); + + type_holder.release(); + } + + /// Helper function which tags all parents of a type using mult. inheritance + void mark_parents_nonsimple(PyTypeObject *value) { + auto t = reinterpret_borrow<tuple>(value->tp_bases); + for (handle h : t) { + auto tinfo2 = get_type_info((PyTypeObject *) h.ptr()); + if (tinfo2) + tinfo2->simple_type = false; + mark_parents_nonsimple((PyTypeObject *) h.ptr()); + } + } + + /// Allocate a metaclass on demand (for static properties) + handle metaclass() { + auto &ht_type = ((PyHeapTypeObject *) m_ptr)->ht_type; + auto &ob_type = PYBIND11_OB_TYPE(ht_type); + + if (ob_type == &PyType_Type) { + std::string name_ = std::string(ht_type.tp_name) + "__Meta"; +#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 + auto ht_qualname = reinterpret_steal<object>(PyUnicode_FromFormat("%U__Meta", attr("__qualname__").ptr())); +#endif + auto name = reinterpret_steal<object>(PYBIND11_FROM_STRING(name_.c_str())); + auto type_holder = reinterpret_steal<object>(PyType_Type.tp_alloc(&PyType_Type, 0)); + if (!type_holder || !name) + pybind11_fail("generic_type::metaclass(): unable to create type object!"); + + auto type = (PyHeapTypeObject*) type_holder.ptr(); + type->ht_name = name.release().ptr(); + +#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 + /* Qualified names for Python >= 3.3 */ + type->ht_qualname = ht_qualname.release().ptr(); +#endif + type->ht_type.tp_name = strdup(name_.c_str()); + type->ht_type.tp_base = ob_type; + type->ht_type.tp_flags |= (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE) & + ~Py_TPFLAGS_HAVE_GC; + + if (PyType_Ready(&type->ht_type) < 0) + pybind11_fail("generic_type::metaclass(): PyType_Ready failed!"); + + ob_type = (PyTypeObject *) type_holder.release().ptr(); + } + return handle((PyObject *) ob_type); + } + + static int init(void *self, PyObject *, PyObject *) { + std::string msg = std::string(Py_TYPE(self)->tp_name) + ": No constructor defined!"; + PyErr_SetString(PyExc_TypeError, msg.c_str()); + return -1; + } + + static PyObject *new_instance(PyTypeObject *type, PyObject *, PyObject *) { + instance<void> *self = (instance<void> *) PyType_GenericAlloc((PyTypeObject *) type, 0); + auto tinfo = detail::get_type_info(type); + self->value = ::operator new(tinfo->type_size); + self->owned = true; + self->holder_constructed = false; + detail::get_internals().registered_instances.emplace(self->value, (PyObject *) self); + return (PyObject *) self; + } + + static void dealloc(instance<void> *self) { + if (self->value) { + auto instance_type = Py_TYPE(self); + auto ®istered_instances = detail::get_internals().registered_instances; + auto range = registered_instances.equal_range(self->value); + bool found = false; + for (auto it = range.first; it != range.second; ++it) { + if (instance_type == Py_TYPE(it->second)) { + registered_instances.erase(it); + found = true; + break; + } + } + if (!found) + pybind11_fail("generic_type::dealloc(): Tried to deallocate unregistered instance!"); + + if (self->weakrefs) + PyObject_ClearWeakRefs((PyObject *) self); + + PyObject **dict_ptr = _PyObject_GetDictPtr((PyObject *) self); + if (dict_ptr) { + Py_CLEAR(*dict_ptr); + } + } + Py_TYPE(self)->tp_free((PyObject*) self); + } + + static int traverse(PyObject *op, visitproc visit, void *arg) { + PyObject *&dict = *_PyObject_GetDictPtr(op); + Py_VISIT(dict); + return 0; + } + + static int clear(PyObject *op) { + PyObject *&dict = *_PyObject_GetDictPtr(op); + Py_CLEAR(dict); + return 0; + } + + void install_buffer_funcs( + buffer_info *(*get_buffer)(PyObject *, void *), + void *get_buffer_data) { + PyHeapTypeObject *type = (PyHeapTypeObject*) m_ptr; + type->ht_type.tp_as_buffer = &type->as_buffer; +#if PY_MAJOR_VERSION < 3 + type->ht_type.tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER; +#endif + type->as_buffer.bf_getbuffer = getbuffer; + type->as_buffer.bf_releasebuffer = releasebuffer; + auto tinfo = detail::get_type_info(&type->ht_type); + tinfo->get_buffer = get_buffer; + tinfo->get_buffer_data = get_buffer_data; + } + + static int getbuffer(PyObject *obj, Py_buffer *view, int flags) { + auto tinfo = detail::get_type_info(Py_TYPE(obj)); + if (view == nullptr || obj == nullptr || !tinfo || !tinfo->get_buffer) { + PyErr_SetString(PyExc_BufferError, "generic_type::getbuffer(): Internal error"); + return -1; + } + 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->len = view->itemsize; + for (auto s : info->shape) + view->len *= s; + if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) + 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]; + } + Py_INCREF(view->obj); + return 0; + } + + static void releasebuffer(PyObject *, Py_buffer *view) { delete (buffer_info *) view->internal; } +}; + +NAMESPACE_END(detail) + +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_valid_class_option = + detail::bool_constant< + is_holder<T>::value || + is_subtype<T>::value || + is_base<T>::value + >; + +public: + using type = type_; + using type_alias = detail::first_of_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>; + + static_assert(detail::all_of_t<is_valid_class_option, options...>::value, + "Unknown/invalid class_ template parameters provided"); + + PYBIND11_OBJECT(class_, generic_type, PyType_Check) + + template <typename... Extra> + class_(handle scope, const char *name, const Extra &... extra) { + detail::type_record record; + record.scope = scope; + record.name = name; + record.type = &typeid(type); + record.type_size = sizeof(detail::conditional_t<has_alias, type_alias, type>); + record.instance_size = sizeof(instance_type); + record.init_holder = init_holder; + record.dealloc = dealloc; + + /* Register base classes specified via template arguments to class_, if any */ + bool unused[] = { (add_base<options>(record), false)..., false }; + (void) unused; + + /* Process optional arguments, if any */ + detail::process_attributes<Extra...>::init(extra..., &record); + + detail::generic_type::initialize(&record); + + if (has_alias) { + auto &instances = pybind11::detail::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 * { + return static_cast<Base *>(reinterpret_cast<type *>(src)); + }); + } + + template <typename Base, detail::enable_if_t<!is_base<Base>::value, int> = 0> + static void add_base(detail::type_record &) { } + + 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), + sibling(getattr(*this, name_, none())), extra...); + attr(cf.name()) = cf; + return *this; + } + + template <typename Func, typename... Extra> class_ & + def_static(const char *name_, Func f, const Extra&... extra) { + cpp_function cf(std::forward<Func>(f), name(name_), scope(*this), + sibling(getattr(*this, name_, none())), extra...); + attr(cf.name()) = cf; + return *this; + } + + template <detail::op_id id, detail::op_type ot, typename L, typename R, typename... Extra> + class_ &def(const detail::op_<id, ot, L, R> &op, const Extra&... extra) { + op.execute(*this, extra...); + return *this; + } + + template <detail::op_id id, detail::op_type ot, typename L, typename R, typename... Extra> + class_ & def_cast(const detail::op_<id, ot, L, R> &op, const Extra&... extra) { + op.execute_cast(*this, extra...); + return *this; + } + + template <typename... Args, typename... Extra> + class_ &def(const detail::init<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) { + init.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) }; + install_buffer_funcs([](PyObject *obj, void *ptr) -> buffer_info* { + detail::type_caster<type> caster; + if (!caster.load(obj, false)) + return nullptr; + return new buffer_info(((capture *) ptr)->func(caster)); + }, ptr); + return *this; + } + + 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)); + 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)); + def_property_readonly(name, fget, return_value_policy::reference_internal, extra...); + return *this; + } + + template <typename D, typename... Extra> + class_ &def_readwrite_static(const char *name, D *pm, const Extra& ...extra) { + cpp_function fget([pm](object) -> const D &{ return *pm; }, scope(*this)), + fset([pm](object, const D &value) { *pm = value; }, scope(*this)); + def_property_static(name, fget, fset, return_value_policy::reference, extra...); + return *this; + } + + template <typename D, typename... Extra> + class_ &def_readonly_static(const char *name, const D *pm, const Extra& ...extra) { + cpp_function fget([pm](object) -> const D &{ return *pm; }, scope(*this)); + def_property_readonly_static(name, fget, return_value_policy::reference, extra...); + return *this; + } + + /// 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...); + } + + /// Uses cpp_function's return_value_policy by default + template <typename... Extra> + class_ &def_property_readonly(const char *name, const cpp_function &fget, const Extra& ...extra) { + return def_property(name, fget, cpp_function(), extra...); + } + + /// Uses return_value_policy::reference by default + template <typename Getter, typename... Extra> + class_ &def_property_readonly_static(const char *name, const Getter &fget, const Extra& ...extra) { + return def_property_readonly_static(name, cpp_function(fget), return_value_policy::reference, extra...); + } + + /// Uses cpp_function's return_value_policy by default + template <typename... Extra> + class_ &def_property_readonly_static(const char *name, const cpp_function &fget, const Extra& ...extra) { + return def_property_static(name, fget, cpp_function(), extra...); + } + + /// Uses return_value_policy::reference_internal by default + 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...); + } + + /// Uses cpp_function's return_value_policy by default + template <typename... Extra> + class_ &def_property(const char *name, const cpp_function &fget, const cpp_function &fset, const Extra& ...extra) { + return def_property_static(name, fget, fset, is_method(*this), extra...); + } + + /// Uses return_value_policy::reference by default + template <typename Getter, typename... Extra> + class_ &def_property_static(const char *name, const Getter &fget, const cpp_function &fset, const Extra& ...extra) { + return def_property_static(name, cpp_function(fget), fset, return_value_policy::reference, extra...); + } + + /// Uses cpp_function's return_value_policy by default + template <typename... Extra> + class_ &def_property_static(const char *name, const cpp_function &fget, const cpp_function &fset, const Extra& ...extra) { + auto rec_fget = get_function_record(fget), rec_fset = get_function_record(fset); + char *doc_prev = rec_fget->doc; /* 'extra' field may include a property-specific documentation string */ + detail::process_attributes<Extra...>::init(extra..., rec_fget); + if (rec_fget->doc && rec_fget->doc != doc_prev) { + free(doc_prev); + rec_fget->doc = strdup(rec_fget->doc); + } + if (rec_fset) { + doc_prev = rec_fset->doc; + detail::process_attributes<Extra...>::init(extra..., rec_fset); + if (rec_fset->doc && rec_fset->doc != doc_prev) { + free(doc_prev); + rec_fset->doc = strdup(rec_fset->doc); + } + } + pybind11::str doc_obj = pybind11::str((rec_fget->doc && pybind11::options::show_user_defined_docstrings()) ? rec_fget->doc : ""); + const auto property = reinterpret_steal<object>( + PyObject_CallFunctionObjArgs((PyObject *) &PyProperty_Type, fget.ptr() ? fget.ptr() : Py_None, + fset.ptr() ? fset.ptr() : Py_None, Py_None, doc_obj.ptr(), nullptr)); + if (rec_fget->is_method && rec_fget->scope) + attr(name) = property; + else + metaclass().attr(name) = property; + return *this; + } + +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 */) { + 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; + } + } + } + + /// Initialize holder object, variant 2: try to construct from existing holder object, if possible + template <typename T = holder_type, + detail::enable_if_t<std::is_copy_constructible<T>::value, int> = 0> + static void init_holder_helper(instance_type *inst, const holder_type *holder_ptr, const void * /* dummy */) { + if (holder_ptr) { + new (&inst->holder) holder_type(*holder_ptr); + inst->holder_constructed = true; + } else if (inst->owned) { + new (&inst->holder) holder_type(inst->value); + inst->holder_constructed = true; + } + } + + /// Initialize holder object, variant 3: holder is not copy constructible (e.g. unique_ptr), always initialize from raw pointer + template <typename T = holder_type, + detail::enable_if_t<!std::is_copy_constructible<T>::value, int> = 0> + static void init_holder_helper(instance_type *inst, const holder_type * /* unused */, const void * /* dummy */) { + if (inst->owned) { + new (&inst->holder) holder_type(inst->value); + inst->holder_constructed = true; + } + } + + /// 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); + } + + static void dealloc(PyObject *inst_) { + instance_type *inst = (instance_type *) inst_; + if (inst->holder_constructed) + inst->holder.~holder_type(); + else if (inst->owned) + ::operator delete(inst->value); + + generic_type::dealloc((detail::instance<void> *) inst); + } + + static detail::function_record *get_function_record(handle h) { + h = detail::get_function(h); + return h ? (detail::function_record *) reinterpret_borrow<capsule>(PyCFunction_GetSelf(h.ptr())) + : nullptr; + } +}; + +/// Binds C++ enumerations and enumeration classes to Python +template <typename Type> class enum_ : public class_<Type> { +public: + using class_<Type>::def; + 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_parent(scope) { + + constexpr bool is_arithmetic = + !std::is_same<detail::first_of_t<arithmetic_tag, void, Extra...>, + void>::value; + + auto entries = new std::unordered_map<Scalar, const char *>(); + def("__repr__", [name, entries](Type value) -> std::string { + auto it = entries->find((Scalar) value); + return std::string(name) + "." + + ((it == entries->end()) ? std::string("???") + : std::string(it->second)); + }); + def("__init__", [](Type& value, Scalar i) { value = (Type)i; }); + def("__init__", [](Type& value, Scalar i) { new (&value) Type((Type) i); }); + def("__int__", [](Type value) { return (Scalar) value; }); + 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) { + def("__lt__", [](const Type &value, Type *value2) { return value2 && value < *value2; }); + def("__gt__", [](const Type &value, Type *value2) { return value2 && value > *value2; }); + def("__le__", [](const Type &value, Type *value2) { return value2 && value <= *value2; }); + def("__ge__", [](const Type &value, Type *value2) { return value2 && value >= *value2; }); + } + if (std::is_convertible<Type, Scalar>::value) { + // Don't provide comparison with the underlying type if the enum isn't convertible, + // i.e. if Type is a scoped enum, mirroring the C++ behaviour. (NB: we explicitly + // convert Type to Scalar below anyway because this needs to compile). + def("__eq__", [](const Type &value, Scalar value2) { return (Scalar) value == value2; }); + def("__ne__", [](const Type &value, Scalar value2) { return (Scalar) value != value2; }); + if (is_arithmetic) { + def("__lt__", [](const Type &value, Scalar value2) { return (Scalar) value < value2; }); + def("__gt__", [](const Type &value, Scalar value2) { return (Scalar) value > value2; }); + def("__le__", [](const Type &value, Scalar value2) { return (Scalar) value <= value2; }); + def("__ge__", [](const Type &value, Scalar value2) { return (Scalar) value >= value2; }); + def("__invert__", [](const Type &value) { return ~((Scalar) value); }); + def("__and__", [](const Type &value, Scalar value2) { return (Scalar) value & value2; }); + def("__or__", [](const Type &value, Scalar value2) { return (Scalar) value | value2; }); + def("__xor__", [](const Type &value, Scalar value2) { return (Scalar) value ^ value2; }); + def("__rand__", [](const Type &value, Scalar value2) { return (Scalar) value & value2; }); + def("__ror__", [](const Type &value, Scalar value2) { return (Scalar) value | value2; }); + def("__rxor__", [](const Type &value, Scalar value2) { return (Scalar) value ^ value2; }); + def("__and__", [](const Type &value, const Type &value2) { return (Scalar) value & (Scalar) value2; }); + def("__or__", [](const Type &value, const Type &value2) { return (Scalar) value | (Scalar) value2; }); + def("__xor__", [](const Type &value, const Type &value2) { return (Scalar) value ^ (Scalar) value2; }); + } + } + 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>()); }); + m_entries = entries; + } + + /// Export enumeration entries into the parent scope + enum_ &export_values() { + PyObject *dict = ((PyTypeObject *) this->m_ptr)->tp_dict; + PyObject *key, *value; + ssize_t pos = 0; + while (PyDict_Next(dict, &pos, &key, &value)) + if (PyObject_IsInstance(value, this->m_ptr)) + m_parent.attr(key) = value; + return *this; + } + + /// Add an enumeration entry + enum_& value(char const* name, Type value) { + this->attr(name) = pybind11::cast(value, return_value_policy::copy); + (*m_entries)[(Scalar) value] = name; + return *this; + } +private: + std::unordered_map<Scalar, const char *> *m_entries; + handle m_parent; +}; + +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(); }); + + weakref wr(nurse, disable_lifesupport); + + patient.inc_ref(); /* reference patient and leak the weak reference */ + (void) wr.release(); +} + +PYBIND11_NOINLINE inline void keep_alive_impl(int Nurse, int Patient, handle args, handle ret) { + handle nurse (Nurse > 0 ? PyTuple_GetItem(args.ptr(), Nurse - 1) : ret.ptr()); + handle patient(Patient > 0 ? PyTuple_GetItem(args.ptr(), Patient - 1) : ret.ptr()); + + keep_alive_impl(nurse, patient); +} + +template <typename Iterator, typename Sentinel, bool KeyIterator, return_value_policy Policy> +struct iterator_state { + Iterator it; + Sentinel end; + bool first; +}; + +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...>(); } + +template <return_value_policy Policy = return_value_policy::reference_internal, + typename Iterator, + typename Sentinel, + typename ValueType = decltype(*std::declval<Iterator>()), + typename... Extra> +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") + .def("__iter__", [](state &s) -> state& { return s; }) + .def("__next__", [](state &s) -> ValueType { + if (!s.first) + ++s.it; + else + s.first = false; + if (s.it == s.end) + throw stop_iteration(); + return *s.it; + }, std::forward<Extra>(extra)..., Policy); + } + + return (iterator) cast(state { first, last, true }); +} + +template <return_value_policy Policy = return_value_policy::reference_internal, + typename Iterator, + typename Sentinel, + typename KeyType = decltype((*std::declval<Iterator>()).first), + typename... Extra> +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") + .def("__iter__", [](state &s) -> state& { return s; }) + .def("__next__", [](state &s) -> KeyType { + if (!s.first) + ++s.it; + else + s.first = false; + if (s.it == s.end) + throw stop_iteration(); + return (*s.it).first; + }, std::forward<Extra>(extra)..., Policy); + } + + return (iterator) cast(state { first, last, true }); +} + +template <return_value_policy Policy = return_value_policy::reference_internal, + typename Type, typename... Extra> iterator make_iterator(Type &value, Extra&&... extra) { + return make_iterator<Policy>(std::begin(value), std::end(value), extra...); +} + +template <return_value_policy Policy = return_value_policy::reference_internal, + typename Type, typename... Extra> iterator make_key_iterator(Type &value, Extra&&... extra) { + return make_key_iterator<Policy>(std::begin(value), std::end(value), extra...); +} + +template <typename InputType, typename OutputType> void implicitly_convertible() { + auto implicit_caster = [](PyObject *obj, PyTypeObject *type) -> PyObject * { + if (!detail::type_caster<InputType>().load(obj, false)) + return nullptr; + tuple args(1); + args[0] = obj; + PyObject *result = PyObject_Call((PyObject *) type, args.ptr(), nullptr); + if (result == nullptr) + PyErr_Clear(); + return result; + }; + + if (auto tinfo = detail::get_type_info(typeid(OutputType))) + tinfo->implicit_conversions.push_back(implicit_caster); + else + pybind11_fail("implicitly_convertible: Unable to find type " + type_id<OutputType>()); +} + +template <typename ExceptionTranslator> +void register_exception_translator(ExceptionTranslator&& translator) { + detail::get_internals().registered_exception_translators.push_front( + std::forward<ExceptionTranslator>(translator)); +} + +/* 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. + * Template type argument is reserved for future use. + */ +template <typename type> +class exception : public object { +public: + exception(handle scope, const char *name, PyObject *base = PyExc_Exception) { + std::string full_name = scope.attr("__name__").cast<std::string>() + + std::string(".") + name; + m_ptr = PyErr_NewException((char *) full_name.c_str(), base, NULL); + if (hasattr(scope, name)) + pybind11_fail("Error during initialization: multiple incompatible " + "definitions with name \"" + std::string(name) + "\""); + scope.attr(name) = *this; + } + + // Sets the current python exception to this exception object with the given message + void operator()(const char *message) { + PyErr_SetString(m_ptr, message); + } +}; + +/** 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. + */ +template <typename CppException> +exception<CppException> ®ister_exception(handle scope, + const char *name, + PyObject *base = PyExc_Exception) { + static exception<CppException> ex(scope, name, base); + register_exception_translator([](std::exception_ptr p) { + if (!p) return; + try { + std::rethrow_exception(p); + } catch (const CppException &e) { + ex(e.what()); + } + }); + return ex; +} + +NAMESPACE_BEGIN(detail) +PYBIND11_NOINLINE inline void print(tuple args, dict kwargs) { + auto strings = tuple(args.size()); + for (size_t i = 0; i < args.size(); ++i) { + strings[i] = str(args[i]); + } + auto sep = kwargs.contains("sep") ? kwargs["sep"] : cast(" "); + auto line = sep.attr("join")(strings); + + object file; + if (kwargs.contains("file")) { + file = kwargs["file"].cast<object>(); + } else { + try { + file = module::import("sys").attr("stdout"); + } catch (const error_already_set &) { + /* If print() is called from code that is executed as + part of garbage collection during interpreter shutdown, + importing 'sys' can fail. Give up rather than crashing the + interpreter in this case. */ + return; + } + } + + auto write = file.attr("write"); + write(line); + write(kwargs.contains("end") ? kwargs["end"] : cast("\n")); + + if (kwargs.contains("flush") && kwargs["flush"].cast<bool>()) + file.attr("flush")(); +} +NAMESPACE_END(detail) + +template <return_value_policy policy = return_value_policy::automatic_reference, typename... Args> +void print(Args &&...args) { + auto c = detail::collect_arguments<policy>(std::forward<Args>(args)...); + detail::print(c.args(), c.kwargs()); +} + +#if defined(WITH_THREAD) + +/* The functions below essentially reproduce the PyGILState_* API using a RAII + * pattern, but there are a few important differences: + * + * 1. When acquiring the GIL from an non-main thread during the finalization + * phase, the GILState API blindly terminates the calling thread, which + * is often not what is wanted. This API does not do this. + * + * 2. The gil_scoped_release function can optionally cut the relationship + * of a PyThreadState and its associated thread, which allows moving it to + * another thread (this is a fairly rare/advanced use case). + * + * 3. The reference count of an acquired thread state can be controlled. This + * can be handy to prevent cases where callbacks issued from an external + * thread would otherwise constantly construct and destroy thread state data + * structures. + * + * See the Python bindings of NanoGUI (http://github.com/wjakob/nanogui) for an + * example which uses features 2 and 3 to migrate the Python thread of + * execution to another thread (to run the event loop on the original thread, + * in this case). + */ + +class gil_scoped_acquire { +public: + PYBIND11_NOINLINE gil_scoped_acquire() { + auto const &internals = detail::get_internals(); + tstate = (PyThreadState *) PyThread_get_key_value(internals.tstate); + + if (!tstate) { + tstate = PyThreadState_New(internals.istate); + #if !defined(NDEBUG) + if (!tstate) + pybind11_fail("scoped_acquire: could not create thread state!"); + #endif + tstate->gilstate_counter = 0; + #if PY_MAJOR_VERSION < 3 + PyThread_delete_key_value(internals.tstate); + #endif + PyThread_set_key_value(internals.tstate, tstate); + } else { + release = detail::get_thread_state_unchecked() != tstate; + } + + if (release) { + /* Work around an annoying assertion in PyThreadState_Swap */ + #if defined(Py_DEBUG) + PyInterpreterState *interp = tstate->interp; + tstate->interp = nullptr; + #endif + PyEval_AcquireThread(tstate); + #if defined(Py_DEBUG) + tstate->interp = interp; + #endif + } + + inc_ref(); + } + + void inc_ref() { + ++tstate->gilstate_counter; + } + + PYBIND11_NOINLINE void dec_ref() { + --tstate->gilstate_counter; + #if !defined(NDEBUG) + if (detail::get_thread_state_unchecked() != tstate) + pybind11_fail("scoped_acquire::dec_ref(): thread state must be current!"); + if (tstate->gilstate_counter < 0) + pybind11_fail("scoped_acquire::dec_ref(): reference count underflow!"); + #endif + if (tstate->gilstate_counter == 0) { + #if !defined(NDEBUG) + if (!release) + pybind11_fail("scoped_acquire::dec_ref(): internal error!"); + #endif + PyThreadState_Clear(tstate); + PyThreadState_DeleteCurrent(); + PyThread_delete_key_value(detail::get_internals().tstate); + release = false; + } + } + + PYBIND11_NOINLINE ~gil_scoped_acquire() { + dec_ref(); + if (release) + PyEval_SaveThread(); + } +private: + PyThreadState *tstate = nullptr; + bool release = true; +}; + +class gil_scoped_release { +public: + explicit gil_scoped_release(bool disassoc = false) : disassoc(disassoc) { + tstate = PyEval_SaveThread(); + if (disassoc) { + auto key = detail::get_internals().tstate; + #if PY_MAJOR_VERSION < 3 + PyThread_delete_key_value(key); + #else + PyThread_set_key_value(key, nullptr); + #endif + } + } + ~gil_scoped_release() { + if (!tstate) + return; + PyEval_RestoreThread(tstate); + if (disassoc) { + auto key = detail::get_internals().tstate; + #if PY_MAJOR_VERSION < 3 + PyThread_delete_key_value(key); + #endif + PyThread_set_key_value(key, tstate); + } + } +private: + PyThreadState *tstate; + bool disassoc; +}; +#else +class gil_scoped_acquire { }; +class gil_scoped_release { }; +#endif + +error_already_set::~error_already_set() { + if (value) { + gil_scoped_acquire gil; + PyErr_Restore(type, value, trace); + PyErr_Clear(); + } +} + +inline function get_type_overload(const void *this_ptr, const detail::type_info *this_type, const char *name) { + handle py_object = detail::get_object_handle(this_ptr, this_type); + if (!py_object) + return function(); + handle type = py_object.get_type(); + auto key = std::make_pair(type.ptr(), name); + + /* Cache functions that aren't overloaded in Python to avoid + many costly Python dictionary lookups below */ + auto &cache = detail::get_internals().inactive_overload_cache; + if (cache.find(key) != cache.end()) + return function(); + + function overload = getattr(py_object, name, function()); + if (overload.is_cpp_function()) { + cache.insert(key); + return function(); + } + + /* Don't call dispatch code if invoked from overridden function */ + PyFrameObject *frame = PyThreadState_Get()->frame; + if (frame && (std::string) str(frame->f_code->co_name) == name && + frame->f_code->co_argcount > 0) { + PyFrame_FastToLocals(frame); + PyObject *self_caller = PyDict_GetItem( + frame->f_locals, PyTuple_GET_ITEM(frame->f_code->co_varnames, 0)); + if (self_caller == py_object.ptr()) + return function(); + } + return overload; +} + +template <class T> function get_overload(const T *this_ptr, const char *name) { + auto tinfo = detail::get_type_info(typeid(T)); + return tinfo ? get_type_overload(this_ptr, tinfo, name) : function(); +} + +#define PYBIND11_OVERLOAD_INT(ret_type, cname, name, ...) { \ + pybind11::gil_scoped_acquire gil; \ + pybind11::function overload = pybind11::get_overload(static_cast<const cname *>(this), name); \ + if (overload) { \ + auto o = overload(__VA_ARGS__); \ + if (pybind11::detail::cast_is_temporary_value_reference<ret_type>::value) { \ + static pybind11::detail::overload_caster_t<ret_type> caster; \ + return pybind11::detail::cast_ref<ret_type>(std::move(o), caster); \ + } \ + else return pybind11::detail::cast_safe<ret_type>(std::move(o)); \ + } \ + } + +#define PYBIND11_OVERLOAD_NAME(ret_type, cname, name, fn, ...) \ + PYBIND11_OVERLOAD_INT(ret_type, cname, name, __VA_ARGS__) \ + return cname::fn(__VA_ARGS__) + +#define PYBIND11_OVERLOAD_PURE_NAME(ret_type, cname, name, fn, ...) \ + PYBIND11_OVERLOAD_INT(ret_type, cname, name, __VA_ARGS__) \ + pybind11::pybind11_fail("Tried to call pure virtual function \"" #cname "::" name "\""); + +#define PYBIND11_OVERLOAD(ret_type, cname, fn, ...) \ + PYBIND11_OVERLOAD_NAME(ret_type, cname, #fn, fn, __VA_ARGS__) + +#define PYBIND11_OVERLOAD_PURE(ret_type, cname, fn, ...) \ + PYBIND11_OVERLOAD_PURE_NAME(ret_type, cname, #fn, fn, __VA_ARGS__) + +NAMESPACE_END(pybind11) + +#if defined(_MSC_VER) +# pragma warning(pop) +#elif defined(__INTEL_COMPILER) +/* Leave ignored warnings on */ +#elif defined(__GNUG__) && !defined(__clang__) +# pragma GCC diagnostic pop +#endif diff --git a/ext/pybind11/include/pybind11/pytypes.h b/ext/pybind11/include/pybind11/pytypes.h new file mode 100644 index 000000000..2b49ecfc9 --- /dev/null +++ b/ext/pybind11/include/pybind11/pytypes.h @@ -0,0 +1,920 @@ +/* + pybind11/typeid.h: Convenience wrapper classes for basic Python types + + 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 "common.h" +#include <utility> +#include <type_traits> + +NAMESPACE_BEGIN(pybind11) + +/* A few forward declarations */ +class handle; class object; +class str; class iterator; +struct arg; struct arg_v; + +NAMESPACE_BEGIN(detail) +class args_proxy; +inline bool isinstance_generic(handle obj, const std::type_info &tp); + +// Accessor forward declarations +template <typename Policy> class accessor; +namespace accessor_policies { + struct obj_attr; + struct str_attr; + struct generic_item; + struct sequence_item; + struct list_item; + struct tuple_item; +} +using obj_attr_accessor = accessor<accessor_policies::obj_attr>; +using str_attr_accessor = accessor<accessor_policies::str_attr>; +using item_accessor = accessor<accessor_policies::generic_item>; +using sequence_accessor = accessor<accessor_policies::sequence_item>; +using list_accessor = accessor<accessor_policies::list_item>; +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>; + +/// Mixin which adds common functions to handle, object and various accessors. +/// The only requirement for `Derived` is to implement `PyObject *Derived::ptr() const`. +template <typename Derived> +class object_api : public pyobject_tag { + const Derived &derived() const { return static_cast<const Derived &>(*this); } + +public: + iterator begin() const; + iterator end() const; + item_accessor operator[](handle key) const; + item_accessor operator[](const char *key) const; + obj_attr_accessor attr(handle key) const; + str_attr_accessor attr(const char *key) const; + args_proxy operator*() const; + template <typename T> bool contains(T &&key) const; + + template <return_value_policy policy = return_value_policy::automatic_reference, typename... Args> + object operator()(Args &&...args) const; + template <return_value_policy policy = return_value_policy::automatic_reference, typename... Args> + PYBIND11_DEPRECATED("call(...) was deprecated in favor of operator()(...)") + object call(Args&&... args) const; + + bool is_none() const { return derived().ptr() == Py_None; } + PYBIND11_DEPRECATED("Instead of obj.str(), use py::str(obj)") + pybind11::str str() const; + + int ref_count() const { return static_cast<int>(Py_REFCNT(derived().ptr())); } + handle get_type() const; +}; + +NAMESPACE_END(detail) + +/// Holds a reference to a Python object (no reference counting) +class handle : public detail::object_api<handle> { +public: + handle() = default; + handle(PyObject *ptr) : m_ptr(ptr) { } // Allow implicit conversion from PyObject* + + PyObject *ptr() const { return m_ptr; } + PyObject *&ptr() { return m_ptr; } + const handle& inc_ref() const { Py_XINCREF(m_ptr); return *this; } + const handle& dec_ref() const { Py_XDECREF(m_ptr); return *this; } + + template <typename T> T cast() const; + explicit operator bool() const { return m_ptr != nullptr; } + bool operator==(const handle &h) const { return m_ptr == h.m_ptr; } + 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; } +protected: + PyObject *m_ptr = nullptr; +}; + +/// Holds a reference to a Python object (with reference counting) +class object : public handle { +public: + object() = default; + PYBIND11_DEPRECATED("Use reinterpret_borrow<object>() or reinterpret_steal<object>()") + object(handle h, bool is_borrowed) : handle(h) { if (is_borrowed) inc_ref(); } + object(const object &o) : handle(o) { inc_ref(); } + object(object &&other) noexcept { m_ptr = other.m_ptr; other.m_ptr = nullptr; } + ~object() { dec_ref(); } + + handle release() { + PyObject *tmp = m_ptr; + m_ptr = nullptr; + return handle(tmp); + } + + object& operator=(const object &other) { + other.inc_ref(); + dec_ref(); + m_ptr = other.m_ptr; + return *this; + } + + object& operator=(object &&other) noexcept { + if (this != &other) { + handle temp(m_ptr); + m_ptr = other.m_ptr; + other.m_ptr = nullptr; + temp.dec_ref(); + } + return *this; + } + + // Calling cast() on an object lvalue just copies (via handle::cast) + template <typename T> T cast() const &; + // Calling on an object rvalue does a move, if needed and/or possible + template <typename T> T cast() &&; + +protected: + // Tags for choosing constructors from raw PyObject * + struct borrowed_t { }; static constexpr borrowed_t borrowed{}; + struct stolen_t { }; static constexpr stolen_t stolen{}; + + template <typename T> friend T reinterpret_borrow(handle); + template <typename T> friend T reinterpret_steal(handle); + +public: + // Only accessible from derived classes and the reinterpret_* functions + object(handle h, borrowed_t) : handle(h) { inc_ref(); } + object(handle h, stolen_t) : handle(h) { } +}; + +/** The following functions don't do any kind of conversion, they simply declare + that a PyObject is a certain type and borrow or steal the reference. */ +template <typename T> T reinterpret_borrow(handle h) { return {h, object::borrowed}; } +template <typename T> T reinterpret_steal(handle h) { return {h, object::stolen}; } + +/// Check if `obj` is an instance of type `T` +template <typename T, detail::enable_if_t<std::is_base_of<object, T>::value, int> = 0> +bool isinstance(handle obj) { return T::_check(obj); } + +template <typename T, detail::enable_if_t<!std::is_base_of<object, T>::value, int> = 0> +bool isinstance(handle obj) { return detail::isinstance_generic(obj, typeid(T)); } + +template <> inline bool isinstance<handle>(handle obj) = delete; +template <> inline bool isinstance<object>(handle obj) { return obj.ptr() != nullptr; } + +inline bool hasattr(handle obj, handle name) { + return PyObject_HasAttr(obj.ptr(), name.ptr()) == 1; +} + +inline bool hasattr(handle obj, const char *name) { + return PyObject_HasAttrString(obj.ptr(), name) == 1; +} + +inline object getattr(handle obj, handle name) { + PyObject *result = PyObject_GetAttr(obj.ptr(), name.ptr()); + if (!result) { throw error_already_set(); } + return reinterpret_steal<object>(result); +} + +inline object getattr(handle obj, const char *name) { + PyObject *result = PyObject_GetAttrString(obj.ptr(), name); + if (!result) { throw error_already_set(); } + return reinterpret_steal<object>(result); +} + +inline object getattr(handle obj, handle name, handle default_) { + if (PyObject *result = PyObject_GetAttr(obj.ptr(), name.ptr())) { + return reinterpret_steal<object>(result); + } else { + PyErr_Clear(); + return reinterpret_borrow<object>(default_); + } +} + +inline object getattr(handle obj, const char *name, handle default_) { + if (PyObject *result = PyObject_GetAttrString(obj.ptr(), name)) { + return reinterpret_steal<object>(result); + } else { + PyErr_Clear(); + return reinterpret_borrow<object>(default_); + } +} + +inline void setattr(handle obj, handle name, handle value) { + if (PyObject_SetAttr(obj.ptr(), name.ptr(), value.ptr()) != 0) { throw error_already_set(); } +} + +inline void setattr(handle obj, const char *name, handle value) { + if (PyObject_SetAttrString(obj.ptr(), name, value.ptr()) != 0) { throw error_already_set(); } +} + +NAMESPACE_BEGIN(detail) +inline handle get_function(handle value) { + if (value) { +#if PY_MAJOR_VERSION >= 3 + if (PyInstanceMethod_Check(value.ptr())) + value = PyInstanceMethod_GET_FUNCTION(value.ptr()); +#endif + if (PyMethod_Check(value.ptr())) + value = PyMethod_GET_FUNCTION(value.ptr()); + } + return value; +} + +// Helper aliases/functions to support implicit casting of values given to python accessors/methods. +// When given a pyobject, this simply returns the pyobject as-is; for other C++ type, the value goes +// through pybind11::cast(obj) to convert it to an `object`. +template <typename T, enable_if_t<is_pyobject<T>::value, int> = 0> +auto object_or_cast(T &&o) -> decltype(std::forward<T>(o)) { return std::forward<T>(o); } +// The following casting version is implemented in cast.h: +template <typename T, enable_if_t<!is_pyobject<T>::value, int> = 0> +object object_or_cast(T &&o); +// Match a PyObject*, which we want to convert directly to handle via its converting constructor +inline handle object_or_cast(PyObject *ptr) { return ptr; } + + +template <typename Policy> +class accessor : public object_api<accessor<Policy>> { + using key_type = typename Policy::key_type; + +public: + accessor(handle obj, key_type key) : obj(obj), key(std::move(key)) { } + + // accessor overload required to override default assignment operator (templates are not allowed + // to replace default compiler-generated assignments). + void operator=(const accessor &a) && { std::move(*this).operator=(handle(a)); } + void operator=(const accessor &a) & { operator=(handle(a)); } + + template <typename T> void operator=(T &&value) && { + Policy::set(obj, key, object_or_cast(std::forward<T>(value))); + } + template <typename T> void operator=(T &&value) & { + get_cache() = reinterpret_borrow<object>(object_or_cast(std::forward<T>(value))); + } + + template <typename T = Policy> + PYBIND11_DEPRECATED("Use of obj.attr(...) as bool is deprecated in favor of pybind11::hasattr(obj, ...)") + explicit operator enable_if_t<std::is_same<T, accessor_policies::str_attr>::value || + std::is_same<T, accessor_policies::obj_attr>::value, bool>() const { + return hasattr(obj, key); + } + template <typename T = Policy> + PYBIND11_DEPRECATED("Use of obj[key] as bool is deprecated in favor of obj.contains(key)") + explicit operator enable_if_t<std::is_same<T, accessor_policies::generic_item>::value, bool>() const { + return obj.contains(key); + } + + operator object() const { return get_cache(); } + PyObject *ptr() const { return get_cache().ptr(); } + template <typename T> T cast() const { return get_cache().template cast<T>(); } + +private: + object &get_cache() const { + if (!cache) { cache = Policy::get(obj, key); } + return cache; + } + +private: + handle obj; + key_type key; + mutable object cache; +}; + +NAMESPACE_BEGIN(accessor_policies) +struct obj_attr { + using key_type = object; + static object get(handle obj, handle key) { return getattr(obj, key); } + static void set(handle obj, handle key, handle val) { setattr(obj, key, val); } +}; + +struct str_attr { + using key_type = const char *; + static object get(handle obj, const char *key) { return getattr(obj, key); } + static void set(handle obj, const char *key, handle val) { setattr(obj, key, val); } +}; + +struct generic_item { + using key_type = object; + + static object get(handle obj, handle key) { + PyObject *result = PyObject_GetItem(obj.ptr(), key.ptr()); + if (!result) { throw error_already_set(); } + return reinterpret_steal<object>(result); + } + + static void set(handle obj, handle key, handle val) { + if (PyObject_SetItem(obj.ptr(), key.ptr(), val.ptr()) != 0) { throw error_already_set(); } + } +}; + +struct sequence_item { + using key_type = size_t; + + static object get(handle obj, size_t index) { + PyObject *result = PySequence_GetItem(obj.ptr(), static_cast<ssize_t>(index)); + if (!result) { throw error_already_set(); } + return reinterpret_borrow<object>(result); + } + + static void set(handle obj, size_t index, handle val) { + // PySequence_SetItem does not steal a reference to 'val' + if (PySequence_SetItem(obj.ptr(), static_cast<ssize_t>(index), val.ptr()) != 0) { + throw error_already_set(); + } + } +}; + +struct list_item { + using key_type = size_t; + + static object get(handle obj, size_t index) { + PyObject *result = PyList_GetItem(obj.ptr(), static_cast<ssize_t>(index)); + if (!result) { throw error_already_set(); } + return reinterpret_borrow<object>(result); + } + + static void set(handle obj, size_t index, handle val) { + // PyList_SetItem steals a reference to 'val' + if (PyList_SetItem(obj.ptr(), static_cast<ssize_t>(index), val.inc_ref().ptr()) != 0) { + throw error_already_set(); + } + } +}; + +struct tuple_item { + using key_type = size_t; + + static object get(handle obj, size_t index) { + PyObject *result = PyTuple_GetItem(obj.ptr(), static_cast<ssize_t>(index)); + if (!result) { throw error_already_set(); } + return reinterpret_borrow<object>(result); + } + + static void set(handle obj, size_t index, handle val) { + // PyTuple_SetItem steals a reference to 'val' + if (PyTuple_SetItem(obj.ptr(), static_cast<ssize_t>(index), val.inc_ref().ptr()) != 0) { + throw error_already_set(); + } + } +}; +NAMESPACE_END(accessor_policies) + +struct dict_iterator { +public: + explicit dict_iterator(handle dict = handle(), ssize_t pos = -1) : dict(dict), pos(pos) { } + dict_iterator& operator++() { + if (!PyDict_Next(dict.ptr(), &pos, &key.ptr(), &value.ptr())) + pos = -1; + return *this; + } + std::pair<handle, handle> operator*() const { + return std::make_pair(key, value); + } + bool operator==(const dict_iterator &it) const { return it.pos == pos; } + bool operator!=(const dict_iterator &it) const { return it.pos != pos; } +private: + handle dict, key, value; + ssize_t pos = 0; +}; + +inline bool PyIterable_Check(PyObject *obj) { + PyObject *iter = PyObject_GetIter(obj); + if (iter) { + Py_DECREF(iter); + return true; + } else { + PyErr_Clear(); + return false; + } +} + +inline bool PyNone_Check(PyObject *o) { return o == Py_None; } + +inline bool PyUnicode_Check_Permissive(PyObject *o) { return PyUnicode_Check(o) || PYBIND11_BYTES_CHECK(o); } + +class kwargs_proxy : public handle { +public: + explicit kwargs_proxy(handle h) : handle(h) { } +}; + +class args_proxy : public handle { +public: + explicit args_proxy(handle h) : handle(h) { } + kwargs_proxy operator*() const { return kwargs_proxy(*this); } +}; + +/// Python argument categories (using PEP 448 terms) +template <typename T> using is_keyword = std::is_base_of<arg, T>; +template <typename T> using is_s_unpacking = std::is_same<args_proxy, T>; // * unpacking +template <typename T> using is_ds_unpacking = std::is_same<kwargs_proxy, T>; // ** unpacking +template <typename T> using is_positional = bool_constant< + !is_keyword<T>::value && !is_s_unpacking<T>::value && !is_ds_unpacking<T>::value +>; +template <typename T> using is_keyword_or_ds = bool_constant< + is_keyword<T>::value || is_ds_unpacking<T>::value +>; + +// Call argument collector forward declarations +template <return_value_policy policy = return_value_policy::automatic_reference> +class simple_collector; +template <return_value_policy policy = return_value_policy::automatic_reference> +class unpacking_collector; + +NAMESPACE_END(detail) + +// TODO: After the deprecated constructors are removed, this macro can be simplified by +// inheriting ctors: `using Parent::Parent`. It's not an option right now because +// the `using` statement triggers the parent deprecation warning even if the ctor +// isn't even used. +#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) { } \ + 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()); } + +#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(); } + +#define PYBIND11_OBJECT(Name, Parent, CheckFun) \ + PYBIND11_OBJECT_COMMON(Name, Parent, CheckFun) \ + /* This is deliberately not 'explicit' to allow implicit conversion from object: */ \ + Name(const object &o) : Parent(o) { } \ + Name(object &&o) : Parent(std::move(o)) { } + +#define PYBIND11_OBJECT_DEFAULT(Name, Parent, CheckFun) \ + PYBIND11_OBJECT(Name, Parent, CheckFun) \ + Name() : Parent() { } + +class iterator : public object { +public: + /** Caveat: copying an iterator does not (and cannot) clone the internal + state of the Python iterable */ + PYBIND11_OBJECT_DEFAULT(iterator, object, PyIter_Check) + + iterator& operator++() { + if (m_ptr) + advance(); + return *this; + } + + /** Caveat: this postincrement operator does not (and cannot) clone the + internal state of the Python iterable. It should only be used to + retrieve the current iterate using <tt>operator*()</tt> */ + iterator operator++(int) { + iterator rv(*this); + rv.value = value; + if (m_ptr) + advance(); + return rv; + } + + bool operator==(const iterator &it) const { return *it == **this; } + bool operator!=(const iterator &it) const { return *it != **this; } + + handle operator*() const { + if (!ready && m_ptr) { + auto& self = const_cast<iterator &>(*this); + self.advance(); + self.ready = true; + } + return value; + } + +private: + void advance() { value = reinterpret_steal<object>(PyIter_Next(m_ptr)); } + +private: + object value = {}; + bool ready = false; +}; + +class iterable : public object { +public: + PYBIND11_OBJECT_DEFAULT(iterable, object, detail::PyIterable_Check) +}; + +class bytes; + +class str : public object { +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) { + 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) { + if (!m_ptr) pybind11_fail("Could not allocate string object!"); + } + + str(const std::string &s) : str(s.data(), s.size()) { } + + explicit str(const bytes &b); + + explicit str(handle h) : object(raw_str(h.ptr()), stolen) { } + + operator std::string() const { + object temp = *this; + if (PyUnicode_Check(m_ptr)) { + temp = reinterpret_steal<object>(PyUnicode_AsUTF8String(m_ptr)); + if (!temp) + pybind11_fail("Unable to extract string contents! (encoding issue)"); + } + char *buffer; + ssize_t length; + if (PYBIND11_BYTES_AS_STRING_AND_SIZE(temp.ptr(), &buffer, &length)) + pybind11_fail("Unable to extract string contents! (invalid type)"); + return std::string(buffer, (size_t) length); + } + + template <typename... Args> + str format(Args &&...args) const { + return attr("format")(std::forward<Args>(args)...); + } + +private: + /// Return string representation -- always returns a new reference, even if already a str + static PyObject *raw_str(PyObject *op) { + PyObject *str_value = PyObject_Str(op); +#if PY_MAJOR_VERSION < 3 + if (!str_value) throw error_already_set(); + PyObject *unicode = PyUnicode_FromEncodedObject(str_value, "utf-8", nullptr); + Py_XDECREF(str_value); str_value = unicode; +#endif + return str_value; + } +}; + +inline namespace literals { +/// String literal version of str +inline str operator"" _s(const char *s, size_t size) { return {s, size}; } +} + +class bytes : public object { +public: + PYBIND11_OBJECT(bytes, object, PYBIND11_BYTES_CHECK) + + // Allow implicit conversion: + bytes(const char *c = "") + : object(PYBIND11_BYTES_FROM_STRING(c), stolen) { + 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) { + if (!m_ptr) pybind11_fail("Could not allocate bytes object!"); + } + + // Allow implicit conversion: + bytes(const std::string &s) : bytes(s.data(), s.size()) { } + + explicit bytes(const pybind11::str &s); + + operator std::string() const { + char *buffer; + ssize_t length; + if (PYBIND11_BYTES_AS_STRING_AND_SIZE(m_ptr, &buffer, &length)) + pybind11_fail("Unable to extract bytes contents!"); + return std::string(buffer, (size_t) length); + } +}; + +inline bytes::bytes(const pybind11::str &s) { + object temp = s; + if (PyUnicode_Check(s.ptr())) { + temp = reinterpret_steal<object>(PyUnicode_AsUTF8String(s.ptr())); + if (!temp) + pybind11_fail("Unable to extract string contents! (encoding issue)"); + } + char *buffer; + ssize_t length; + if (PYBIND11_BYTES_AS_STRING_AND_SIZE(temp.ptr(), &buffer, &length)) + pybind11_fail("Unable to extract string contents! (invalid type)"); + auto obj = reinterpret_steal<object>(PYBIND11_BYTES_FROM_STRING_AND_SIZE(buffer, length)); + if (!obj) + pybind11_fail("Could not allocate bytes object!"); + m_ptr = obj.release().ptr(); +} + +inline str::str(const bytes& b) { + char *buffer; + ssize_t length; + if (PYBIND11_BYTES_AS_STRING_AND_SIZE(b.ptr(), &buffer, &length)) + pybind11_fail("Unable to extract bytes contents!"); + auto obj = reinterpret_steal<object>(PyUnicode_FromStringAndSize(buffer, (ssize_t) length)); + if (!obj) + pybind11_fail("Could not allocate string object!"); + m_ptr = obj.release().ptr(); +} + +class none : public object { +public: + PYBIND11_OBJECT(none, object, detail::PyNone_Check) + none() : object(Py_None, borrowed) { } +}; + +class bool_ : public object { +public: + PYBIND11_OBJECT_CVT(bool_, object, PyBool_Check, raw_bool) + bool_() : object(Py_False, borrowed) { } + // Allow implicit conversion from and to `bool`: + bool_(bool value) : object(value ? Py_True : Py_False, borrowed) { } + operator bool() const { return m_ptr && PyLong_AsLong(m_ptr) != 0; } + +private: + /// Return the truth value of an object -- always returns a new reference + static PyObject *raw_bool(PyObject *op) { + const auto value = PyObject_IsTrue(op); + if (value == -1) return nullptr; + return handle(value ? Py_True : Py_False).inc_ref().ptr(); + } +}; + +class int_ : public object { +public: + PYBIND11_OBJECT_CVT(int_, object, PYBIND11_LONG_CHECK, PyNumber_Long) + int_() : object(PyLong_FromLong(0), stolen) { } + // Allow implicit conversion from C++ integral types: + template <typename T, + detail::enable_if_t<std::is_integral<T>::value, int> = 0> + int_(T value) { + if (sizeof(T) <= sizeof(long)) { + if (std::is_signed<T>::value) + m_ptr = PyLong_FromLong((long) value); + else + m_ptr = PyLong_FromUnsignedLong((unsigned long) value); + } else { + if (std::is_signed<T>::value) + m_ptr = PyLong_FromLongLong((long long) value); + else + m_ptr = PyLong_FromUnsignedLongLong((unsigned long long) value); + } + if (!m_ptr) pybind11_fail("Could not allocate int object!"); + } + + 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); + } + } +}; + +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) { + if (!m_ptr) pybind11_fail("Could not allocate float object!"); + } + float_(double value = .0) : object(PyFloat_FromDouble((double) value), stolen) { + if (!m_ptr) pybind11_fail("Could not allocate float object!"); + } + operator float() const { return (float) PyFloat_AsDouble(m_ptr); } + operator double() const { return (double) PyFloat_AsDouble(m_ptr); } +}; + +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) { + if (!m_ptr) pybind11_fail("Could not allocate weak reference!"); + } +}; + +class slice : public object { +public: + PYBIND11_OBJECT_DEFAULT(slice, object, PySlice_Check) + slice(ssize_t start_, ssize_t stop_, ssize_t step_) { + int_ start(start_), stop(stop_), step(step_); + m_ptr = PySlice_New(start.ptr(), stop.ptr(), step.ptr()); + if (!m_ptr) pybind11_fail("Could not allocate slice object!"); + } + bool compute(size_t length, size_t *start, size_t *stop, size_t *step, + size_t *slicelength) const { + return PySlice_GetIndicesEx((PYBIND11_SLICE_OBJECT *) m_ptr, + (ssize_t) length, (ssize_t *) start, + (ssize_t *) stop, (ssize_t *) step, + (ssize_t *) slicelength) == 0; + } +}; + +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)) { } + explicit capsule(const void *value, void (*destruct)(PyObject *) = nullptr) + : object(PyCapsule_New(const_cast<void*>(value), nullptr, destruct), stolen) { + if (!m_ptr) pybind11_fail("Could not allocate capsule object!"); + } + template <typename T> operator T *() const { + T * result = static_cast<T *>(PyCapsule_GetPointer(m_ptr, nullptr)); + if (!result) pybind11_fail("Unable to extract capsule contents!"); + return result; + } +}; + +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) { + if (!m_ptr) pybind11_fail("Could not allocate tuple object!"); + } + size_t size() const { return (size_t) PyTuple_Size(m_ptr); } + detail::tuple_accessor operator[](size_t index) const { return {*this, index}; } +}; + +class dict : public object { +public: + PYBIND11_OBJECT_CVT(dict, object, PyDict_Check, raw_dict) + dict() : object(PyDict_New(), stolen) { + if (!m_ptr) pybind11_fail("Could not allocate dict object!"); + } + template <typename... Args, + typename = detail::enable_if_t<detail::all_of_t<detail::is_keyword_or_ds, Args...>::value>, + // MSVC workaround: it can't compile an out-of-line definition, so defer the collector + typename collector = detail::deferred_t<detail::unpacking_collector<>, Args...>> + explicit dict(Args &&...args) : dict(collector(std::forward<Args>(args)...).kwargs()) { } + + size_t size() const { return (size_t) PyDict_Size(m_ptr); } + detail::dict_iterator begin() const { return (++detail::dict_iterator(*this, 0)); } + detail::dict_iterator end() const { return detail::dict_iterator(); } + void clear() const { PyDict_Clear(ptr()); } + bool contains(handle key) const { return PyDict_Contains(ptr(), key.ptr()) == 1; } + bool contains(const char *key) const { return PyDict_Contains(ptr(), pybind11::str(key).ptr()) == 1; } + +private: + /// Call the `dict` Python type -- always returns a new reference + static PyObject *raw_dict(PyObject *op) { + if (PyDict_Check(op)) + return handle(op).inc_ref().ptr(); + return PyObject_CallFunctionObjArgs((PyObject *) &PyDict_Type, op, nullptr); + } +}; + +class sequence : public object { +public: + PYBIND11_OBJECT(sequence, object, PySequence_Check) + size_t size() const { return (size_t) PySequence_Size(m_ptr); } + detail::sequence_accessor operator[](size_t index) const { return {*this, index}; } +}; + +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) { + if (!m_ptr) pybind11_fail("Could not allocate list object!"); + } + size_t size() const { return (size_t) PyList_Size(m_ptr); } + detail::list_accessor operator[](size_t index) const { return {*this, index}; } + template <typename T> void append(T &&val) const { + PyList_Append(m_ptr, detail::object_or_cast(std::forward<T>(val)).ptr()); + } +}; + +class args : public tuple { PYBIND11_OBJECT_DEFAULT(args, tuple, PyTuple_Check) }; +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) { + if (!m_ptr) pybind11_fail("Could not allocate set object!"); + } + size_t size() const { return (size_t) PySet_Size(m_ptr); } + template <typename T> bool add(T &&val) const { + return PySet_Add(m_ptr, detail::object_or_cast(std::forward<T>(val)).ptr()) == 0; + } + void clear() const { PySet_Clear(m_ptr); } +}; + +class function : public object { +public: + PYBIND11_OBJECT_DEFAULT(function, object, PyCallable_Check) + bool is_cpp_function() const { + handle fun = detail::get_function(m_ptr); + return fun && PyCFunction_Check(fun.ptr()); + } +}; + +class buffer : public object { +public: + PYBIND11_OBJECT_DEFAULT(buffer, object, PyObject_CheckBuffer) + + buffer_info request(bool writable = false) { + 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) + throw error_already_set(); + return buffer_info(view); + } +}; + +class memoryview : public object { +public: + explicit memoryview(const buffer_info& info) { + static Py_buffer buf { }; + // Py_buffer uses signed sizes, strides and shape!.. + 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.format = const_cast<char *>(info.format.c_str()); + buf.ndim = (int) info.ndim; + buf.len = (Py_ssize_t) 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]); + } + buf.strides = py_strides.data(); + buf.shape = py_shape.data(); + buf.suboffsets = nullptr; + buf.readonly = false; + buf.internal = nullptr; + + m_ptr = PyMemoryView_FromBuffer(&buf); + if (!m_ptr) + pybind11_fail("Unable to create memoryview from buffer descriptor"); + } + + PYBIND11_OBJECT_CVT(memoryview, object, PyMemoryView_Check, PyMemoryView_FromObject) +}; + +inline size_t len(handle h) { + ssize_t result = PyObject_Length(h.ptr()); + if (result < 0) + pybind11_fail("Unable to compute length of object"); + return (size_t) result; +} + +inline str repr(handle h) { + PyObject *str_value = PyObject_Repr(h.ptr()); + if (!str_value) throw error_already_set(); +#if PY_MAJOR_VERSION < 3 + PyObject *unicode = PyUnicode_FromEncodedObject(str_value, "utf-8", nullptr); + Py_XDECREF(str_value); str_value = unicode; + if (!str_value) throw error_already_set(); +#endif + return reinterpret_steal<str>(str_value); +} + +NAMESPACE_BEGIN(detail) +template <typename D> iterator object_api<D>::begin() const { + return reinterpret_steal<iterator>(PyObject_GetIter(derived().ptr())); +} +template <typename D> iterator object_api<D>::end() const { + return {}; +} +template <typename D> item_accessor object_api<D>::operator[](handle key) const { + return {derived(), reinterpret_borrow<object>(key)}; +} +template <typename D> item_accessor object_api<D>::operator[](const char *key) const { + return {derived(), pybind11::str(key)}; +} +template <typename D> obj_attr_accessor object_api<D>::attr(handle key) const { + return {derived(), reinterpret_borrow<object>(key)}; +} +template <typename D> str_attr_accessor object_api<D>::attr(const char *key) const { + return {derived(), key}; +} +template <typename D> args_proxy object_api<D>::operator*() const { + return args_proxy(derived().ptr()); +} +template <typename D> template <typename T> bool object_api<D>::contains(T &&key) const { + return attr("__contains__")(std::forward<T>(key)).template cast<bool>(); +} + +template <typename D> +pybind11::str object_api<D>::str() const { return pybind11::str(derived()); } + +template <typename D> +handle object_api<D>::get_type() const { return (PyObject *) Py_TYPE(derived().ptr()); } + +NAMESPACE_END(detail) +NAMESPACE_END(pybind11) diff --git a/ext/pybind11/include/pybind11/stl.h b/ext/pybind11/include/pybind11/stl.h new file mode 100644 index 000000000..d4b0fc914 --- /dev/null +++ b/ext/pybind11/include/pybind11/stl.h @@ -0,0 +1,276 @@ +/* + pybind11/stl.h: Transparent conversion for STL data types + + 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 "pybind11.h" +#include <set> +#include <unordered_set> +#include <map> +#include <unordered_map> +#include <iostream> +#include <list> +#include <valarray> + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable: 4127) // warning C4127: Conditional expression is constant +#endif + +#ifdef __has_include +// std::optional (but including it in c++14 mode isn't allowed) +# if defined(PYBIND11_CPP17) && __has_include(<optional>) +# include <optional> +# define PYBIND11_HAS_OPTIONAL 1 +# endif +// 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 +# endif +#endif + +NAMESPACE_BEGIN(pybind11) +NAMESPACE_BEGIN(detail) + +template <typename Type, typename Key> struct set_caster { + using type = Type; + using key_conv = make_caster<Key>; + + bool load(handle src, bool convert) { + if (!isinstance<pybind11::set>(src)) + return false; + auto s = reinterpret_borrow<pybind11::set>(src); + value.clear(); + key_conv conv; + for (auto entry : s) { + if (!conv.load(entry, convert)) + return false; + value.insert(cast_op<Key>(conv)); + } + return true; + } + + static handle cast(const type &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)); + if (!value_ || !s.add(value_)) + return handle(); + } + return s.release(); + } + + PYBIND11_TYPE_CASTER(type, _("Set[") + key_conv::name() + _("]")); +}; + +template <typename Type, typename Key, typename Value> struct map_caster { + using key_conv = make_caster<Key>; + using value_conv = make_caster<Value>; + + bool load(handle src, bool convert) { + if (!isinstance<dict>(src)) + return false; + auto d = reinterpret_borrow<dict>(src); + key_conv kconv; + value_conv vconv; + value.clear(); + for (auto it : d) { + 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)); + } + return true; + } + + static handle cast(const Type &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)); + if (!key || !value) + return handle(); + d[key] = value; + } + return d.release(); + } + + PYBIND11_TYPE_CASTER(Type, _("Dict[") + key_conv::name() + _(", ") + value_conv::name() + _("]")); +}; + +template <typename Type, typename Value> struct list_caster { + using value_conv = make_caster<Value>; + + bool load(handle src, bool convert) { + 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) { + if (!conv.load(it, convert)) + return false; + value.push_back(cast_op<Value>(conv)); + } + return true; + } + +private: + template <typename T = Type, + enable_if_t<std::is_same<decltype(std::declval<T>().reserve(0)), void>::value, int> = 0> + void reserve_maybe(sequence s, Type *) { value.reserve(s.size()); } + void reserve_maybe(sequence, void *) { } + +public: + static handle cast(const Type &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)); + if (!value_) + return handle(); + PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference + } + return l.release(); + } + + PYBIND11_TYPE_CASTER(Type, _("List[") + value_conv::name() + _("]")); +}; + +template <typename Type, typename Alloc> struct type_caster<std::vector<Type, Alloc>> + : list_caster<std::vector<Type, Alloc>, Type> { }; + +template <typename Type, typename Alloc> struct type_caster<std::list<Type, Alloc>> + : list_caster<std::list<Type, Alloc>, Type> { }; + +template <typename ArrayType, typename Value, bool Resizable, size_t Size = 0> struct array_caster { + using value_conv = make_caster<Value>; + +private: + template <bool R = Resizable> + bool require_size(enable_if_t<R, size_t> size) { + if (value.size() != size) + value.resize(size); + return true; + } + template <bool R = Resizable> + bool require_size(enable_if_t<!R, size_t> size) { + return size == Size; + } + +public: + bool load(handle src, bool convert) { + if (!isinstance<list>(src)) + return false; + auto l = reinterpret_borrow<list>(src); + if (!require_size(l.size())) + return false; + value_conv conv; + size_t ctr = 0; + for (auto it : l) { + if (!conv.load(it, convert)) + return false; + value[ctr++] = cast_op<Value>(conv); + } + return true; + } + + static handle cast(const ArrayType &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)); + if (!value_) + return handle(); + PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference + } + return l.release(); + } + + PYBIND11_TYPE_CASTER(ArrayType, _("List[") + value_conv::name() + _<Resizable>(_(""), _("[") + _<Size>() + _("]")) + _("]")); +}; + +template <typename Type, size_t Size> struct type_caster<std::array<Type, Size>> + : array_caster<std::array<Type, Size>, Type, false, Size> { }; + +template <typename Type> struct type_caster<std::valarray<Type>> + : array_caster<std::valarray<Type>, Type, true> { }; + +template <typename Key, typename Compare, typename Alloc> struct type_caster<std::set<Key, Compare, Alloc>> + : set_caster<std::set<Key, Compare, Alloc>, Key> { }; + +template <typename Key, typename Hash, typename Equal, typename Alloc> struct type_caster<std::unordered_set<Key, Hash, Equal, Alloc>> + : set_caster<std::unordered_set<Key, Hash, Equal, Alloc>, Key> { }; + +template <typename Key, typename Value, typename Compare, typename Alloc> struct type_caster<std::map<Key, Value, Compare, Alloc>> + : map_caster<std::map<Key, Value, Compare, Alloc>, Key, Value> { }; + +template <typename Key, typename Value, typename Hash, typename Equal, typename Alloc> struct type_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>> + : map_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>, Key, Value> { }; + +// This type caster is intended to be used for std::optional and std::experimental::optional +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) { + if (!src) + return none().inc_ref(); + return value_conv::cast(*src, policy, parent); + } + + bool load(handle src, bool convert) { + if (!src) { + return false; + } else if (src.is_none()) { + value = {}; // nullopt + return true; + } + value_conv inner_caster; + if (!inner_caster.load(src, convert)) + return false; + + value.emplace(cast_op<typename T::value_type>(inner_caster)); + return true; + } + + PYBIND11_TYPE_CASTER(T, _("Optional[") + value_conv::name() + _("]")); +}; + +#if PYBIND11_HAS_OPTIONAL +template<typename T> struct type_caster<std::optional<T>> + : public optional_caster<std::optional<T>> {}; + +template<> struct type_caster<std::nullopt_t> + : public void_caster<std::nullopt_t> {}; +#endif + +#if PYBIND11_HAS_EXP_OPTIONAL +template<typename T> struct type_caster<std::experimental::optional<T>> + : public optional_caster<std::experimental::optional<T>> {}; + +template<> struct type_caster<std::experimental::nullopt_t> + : public void_caster<std::experimental::nullopt_t> {}; +#endif + +NAMESPACE_END(detail) + +inline std::ostream &operator<<(std::ostream &os, const handle &obj) { + os << (std::string) str(obj); + return os; +} + +NAMESPACE_END(pybind11) + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif diff --git a/ext/pybind11/include/pybind11/stl_bind.h b/ext/pybind11/include/pybind11/stl_bind.h new file mode 100644 index 000000000..ef9950ebb --- /dev/null +++ b/ext/pybind11/include/pybind11/stl_bind.h @@ -0,0 +1,541 @@ +/* + pybind11/std_bind.h: Binding generators for STL data types + + Copyright (c) 2016 Sergey Lyskov and Wenzel Jakob + + 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 "common.h" +#include "operators.h" + +#include <algorithm> +#include <sstream> + +NAMESPACE_BEGIN(pybind11) +NAMESPACE_BEGIN(detail) + +/* SFINAE helper class used by 'is_comparable */ +template <typename T> struct container_traits { + template <typename T2> static std::true_type test_comparable(decltype(std::declval<const T2 &>() == std::declval<const T2 &>())*); + template <typename T2> static std::false_type test_comparable(...); + template <typename T2> static std::true_type test_value(typename T2::value_type *); + template <typename T2> static std::false_type test_value(...); + template <typename T2> static std::true_type test_pair(typename T2::first_type *, typename T2::second_type *); + template <typename T2> static std::false_type test_pair(...); + + static constexpr const bool is_comparable = std::is_same<std::true_type, decltype(test_comparable<T>(nullptr))>::value; + static constexpr const bool is_pair = std::is_same<std::true_type, decltype(test_pair<T>(nullptr, nullptr))>::value; + static constexpr const bool is_vector = std::is_same<std::true_type, decltype(test_value<T>(nullptr))>::value; + static constexpr const bool is_element = !is_pair && !is_vector; +}; + +/* Default: is_comparable -> std::false_type */ +template <typename T, typename SFINAE = void> +struct is_comparable : std::false_type { }; + +/* For non-map data structures, check whether operator== can be instantiated */ +template <typename T> +struct is_comparable< + T, enable_if_t<container_traits<T>::is_element && + container_traits<T>::is_comparable>> + : std::true_type { }; + +/* For a vector/map data structure, recursively check the value type (which is std::pair for maps) */ +template <typename T> +struct is_comparable<T, enable_if_t<container_traits<T>::is_vector>> { + static constexpr const bool value = + is_comparable<typename T::value_type>::value; +}; + +/* For pairs, recursively check the two data types */ +template <typename T> +struct is_comparable<T, enable_if_t<container_traits<T>::is_pair>> { + static constexpr const bool value = + is_comparable<typename T::first_type>::value && + is_comparable<typename T::second_type>::value; +}; + +/* Fallback functions */ +template <typename, typename, typename... Args> void vector_if_copy_constructible(const Args &...) { } +template <typename, typename, typename... Args> void vector_if_equal_operator(const Args &...) { } +template <typename, typename, typename... Args> void vector_if_insertion_operator(const Args &...) { } +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) { + + cl.def(pybind11::init<const Vector &>(), "Copy constructor"); +} + +template<typename Vector, typename Class_> +void vector_if_equal_operator(enable_if_t<is_comparable<Vector>::value, Class_> &cl) { + using T = typename Vector::value_type; + + cl.def(self == self); + cl.def(self != self); + + cl.def("count", + [](const Vector &v, const T &x) { + return std::count(v.begin(), v.end(), x); + }, + arg("x"), + "Return the number of times ``x`` appears in the list" + ); + + cl.def("remove", [](Vector &v, const T &x) { + auto p = std::find(v.begin(), v.end(), x); + if (p != v.end()) + v.erase(p); + else + throw pybind11::value_error(); + }, + arg("x"), + "Remove the first item from the list whose value is x. " + "It is an error if there is no such item." + ); + + cl.def("__contains__", + [](const Vector &v, const T &x) { + return std::find(v.begin(), v.end(), x) != v.end(); + }, + arg("x"), + "Return true the container contains ``x``" + ); +} + +// Vector modifiers -- requires a copyable vector_type: +// (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) { + using T = typename Vector::value_type; + using SizeType = typename Vector::size_type; + using DiffType = typename Vector::difference_type; + + cl.def("append", + [](Vector &v, const T &value) { v.push_back(value); }, + 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("extend", + [](Vector &v, const Vector &src) { + v.reserve(v.size() + src.size()); + v.insert(v.end(), src.begin(), src.end()); + }, + arg("L"), + "Extend the list by appending all the items in the given list" + ); + + cl.def("insert", + [](Vector &v, SizeType i, const T &x) { + v.insert(v.begin() + (DiffType) i, x); + }, + arg("i") , arg("x"), + "Insert an item at a given position." + ); + + cl.def("pop", + [](Vector &v) { + if (v.empty()) + throw pybind11::index_error(); + T t = v.back(); + v.pop_back(); + return t; + }, + "Remove and return the last item" + ); + + cl.def("pop", + [](Vector &v, SizeType i) { + if (i >= v.size()) + throw pybind11::index_error(); + T t = v[i]; + v.erase(v.begin() + (DiffType) i); + return t; + }, + arg("i"), + "Remove and return the item at index ``i``" + ); + + cl.def("__setitem__", + [](Vector &v, SizeType i, const T &t) { + if (i >= v.size()) + throw pybind11::index_error(); + v[i] = t; + } + ); + + /// Slicing protocol + cl.def("__getitem__", + [](const Vector &v, slice slice) -> Vector * { + size_t start, stop, step, slicelength; + + if (!slice.compute(v.size(), &start, &stop, &step, &slicelength)) + throw pybind11::error_already_set(); + + Vector *seq = new Vector(); + seq->reserve((size_t) slicelength); + + for (size_t i=0; i<slicelength; ++i) { + seq->push_back(v[start]); + start += step; + } + return seq; + }, + arg("s"), + "Retrieve list elements using a slice object" + ); + + cl.def("__setitem__", + [](Vector &v, slice slice, const Vector &value) { + size_t start, stop, step, slicelength; + if (!slice.compute(v.size(), &start, &stop, &step, &slicelength)) + throw pybind11::error_already_set(); + + if (slicelength != value.size()) + throw std::runtime_error("Left and right hand size of slice assignment have different sizes!"); + + for (size_t i=0; i<slicelength; ++i) { + v[start] = value[i]; + start += step; + } + }, + "Assign list elements using a slice object" + ); + + cl.def("__delitem__", + [](Vector &v, SizeType i) { + if (i >= v.size()) + throw pybind11::index_error(); + v.erase(v.begin() + DiffType(i)); + }, + "Delete the list elements at index ``i``" + ); + + cl.def("__delitem__", + [](Vector &v, slice slice) { + size_t start, stop, step, slicelength; + + if (!slice.compute(v.size(), &start, &stop, &step, &slicelength)) + throw pybind11::error_already_set(); + + if (step == 1 && false) { + v.erase(v.begin() + (DiffType) start, v.begin() + DiffType(start + slicelength)); + } else { + for (size_t i = 0; i < slicelength; ++i) { + v.erase(v.begin() + DiffType(start)); + start += step - 1; + } + } + }, + "Delete list elements using a slice object" + ); + +} + +// If the type has an operator[] that doesn't return a reference (most notably std::vector<bool>), +// we have to access by copying; otherwise we return by reference. +template <typename Vector> using vector_needs_copy = bool_constant< + !std::is_same<decltype(std::declval<Vector>()[typename Vector::size_type()]), typename Vector::value_type &>::value>; + +// The usual case: access and iterate by reference +template <typename Vector, typename Class_> +void vector_accessor(enable_if_t<!vector_needs_copy<Vector>::value, Class_> &cl) { + using T = typename Vector::value_type; + using SizeType = typename Vector::size_type; + using ItType = typename Vector::iterator; + + cl.def("__getitem__", + [](Vector &v, SizeType i) -> T & { + if (i >= v.size()) + throw pybind11::index_error(); + return v[i]; + }, + return_value_policy::reference_internal // ref + keepalive + ); + + cl.def("__iter__", + [](Vector &v) { + return pybind11::make_iterator< + return_value_policy::reference_internal, ItType, ItType, T&>( + v.begin(), v.end()); + }, + keep_alive<0, 1>() /* Essential: keep list alive while iterator exists */ + ); +} + +// The case for special objects, like std::vector<bool>, that have to be returned-by-copy: +template <typename Vector, typename Class_> +void vector_accessor(enable_if_t<vector_needs_copy<Vector>::value, Class_> &cl) { + using T = typename Vector::value_type; + using SizeType = typename Vector::size_type; + using ItType = typename Vector::iterator; + cl.def("__getitem__", + [](const Vector &v, SizeType i) -> T { + if (i >= v.size()) + throw pybind11::index_error(); + return v[i]; + } + ); + + cl.def("__iter__", + [](Vector &v) { + return pybind11::make_iterator< + return_value_policy::copy, ItType, ItType, T>( + v.begin(), v.end()); + }, + keep_alive<0, 1>() /* Essential: keep list alive while iterator exists */ + ); +} + +template <typename Vector, typename Class_> auto vector_if_insertion_operator(Class_ &cl, std::string const &name) + -> decltype(std::declval<std::ostream&>() << std::declval<typename Vector::value_type>(), void()) { + using size_type = typename Vector::size_type; + + cl.def("__repr__", + [name](Vector &v) { + std::ostringstream s; + s << name << '['; + for (size_type i=0; i < v.size(); ++i) { + s << v[i]; + if (i != v.size() - 1) + s << ", "; + } + s << ']'; + return s.str(); + }, + "Return the canonical string representation of this list." + ); +} + +NAMESPACE_END(detail) + +// +// std::vector +// +template <typename Vector, typename holder_type = std::unique_ptr<Vector>, typename... Args> +pybind11::class_<Vector, holder_type> bind_vector(pybind11::module &m, std::string const &name, Args&&... args) { + using Class_ = pybind11::class_<Vector, holder_type>; + + Class_ cl(m, name.c_str(), std::forward<Args>(args)...); + + cl.def(pybind11::init<>()); + + // Register copy constructor (if possible) + detail::vector_if_copy_constructible<Vector, Class_>(cl); + + // Register comparison-related operators and functions (if possible) + detail::vector_if_equal_operator<Vector, Class_>(cl); + + // Register stream insertion operator (if possible) + detail::vector_if_insertion_operator<Vector, Class_>(cl, name); + + // Modifiers require copyable vector value type + detail::vector_modifiers<Vector, Class_>(cl); + + // Accessor and iterator; return by value if copyable, otherwise we return by ref + keep-alive + detail::vector_accessor<Vector, Class_>(cl); + + cl.def("__bool__", + [](const Vector &v) -> bool { + return !v.empty(); + }, + "Check whether the list is nonempty" + ); + + cl.def("__len__", &Vector::size); + + + + +#if 0 + // C++ style functions deprecated, leaving it here as an example + cl.def(pybind11::init<size_type>()); + + cl.def("resize", + (void (Vector::*) (size_type count)) & Vector::resize, + "changes the number of elements stored"); + + cl.def("erase", + [](Vector &v, SizeType i) { + if (i >= v.size()) + throw pybind11::index_error(); + v.erase(v.begin() + i); + }, "erases element at index ``i``"); + + cl.def("empty", &Vector::empty, "checks whether the container is empty"); + cl.def("size", &Vector::size, "returns the number of elements"); + cl.def("push_back", (void (Vector::*)(const T&)) &Vector::push_back, "adds an element to the end"); + cl.def("pop_back", &Vector::pop_back, "removes the last element"); + + cl.def("max_size", &Vector::max_size, "returns the maximum possible number of elements"); + cl.def("reserve", &Vector::reserve, "reserves storage"); + cl.def("capacity", &Vector::capacity, "returns the number of elements that can be held in currently allocated storage"); + cl.def("shrink_to_fit", &Vector::shrink_to_fit, "reduces memory usage by freeing unused memory"); + + cl.def("clear", &Vector::clear, "clears the contents"); + cl.def("swap", &Vector::swap, "swaps the contents"); + + cl.def("front", [](Vector &v) { + if (v.size()) return v.front(); + else throw pybind11::index_error(); + }, "access the first element"); + + cl.def("back", [](Vector &v) { + if (v.size()) return v.back(); + else throw pybind11::index_error(); + }, "access the last element "); + +#endif + + return cl; +} + + + +// +// std::map, std::unordered_map +// + +NAMESPACE_BEGIN(detail) + +/* Fallback functions */ +template <typename, typename, typename... Args> void map_if_insertion_operator(const Args &...) { } +template <typename, typename, typename... Args> void map_assignment(const Args &...) { } + +// Map assignment when copy-assignable: just copy the value +template <typename Map, typename Class_> +void map_assignment(enable_if_t<std::is_copy_assignable<typename Map::mapped_type>::value, Class_> &cl) { + using KeyType = typename Map::key_type; + using MappedType = typename Map::mapped_type; + + cl.def("__setitem__", + [](Map &m, const KeyType &k, const MappedType &v) { + auto it = m.find(k); + if (it != m.end()) it->second = v; + else m.emplace(k, v); + } + ); +} + +// Not copy-assignable, but still copy-constructible: we can update the value by erasing and reinserting +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, + Class_> &cl) { + using KeyType = typename Map::key_type; + using MappedType = typename Map::mapped_type; + + cl.def("__setitem__", + [](Map &m, const KeyType &k, const MappedType &v) { + // We can't use m[k] = v; because value type might not be default constructable + auto r = m.emplace(k, v); + if (!r.second) { + // value type is not copy assignable so the only way to insert it is to erase it first... + m.erase(r.first); + m.emplace(k, v); + } + } + ); +} + + +template <typename Map, typename Class_> auto map_if_insertion_operator(Class_ &cl, std::string const &name) +-> decltype(std::declval<std::ostream&>() << std::declval<typename Map::key_type>() << std::declval<typename Map::mapped_type>(), void()) { + + cl.def("__repr__", + [name](Map &m) { + std::ostringstream s; + s << name << '{'; + bool f = false; + for (auto const &kv : m) { + if (f) + s << ", "; + s << kv.first << ": " << kv.second; + f = true; + } + s << '}'; + return s.str(); + }, + "Return the canonical string representation of this map." + ); +} + + +NAMESPACE_END(detail) + +template <typename Map, typename holder_type = std::unique_ptr<Map>, typename... Args> +pybind11::class_<Map, holder_type> bind_map(module &m, const std::string &name, Args&&... args) { + using KeyType = typename Map::key_type; + using MappedType = typename Map::mapped_type; + using Class_ = pybind11::class_<Map, holder_type>; + + Class_ cl(m, name.c_str(), std::forward<Args>(args)...); + + cl.def(pybind11::init<>()); + + // Register stream insertion operator (if possible) + detail::map_if_insertion_operator<Map, Class_>(cl, name); + + cl.def("__bool__", + [](const Map &m) -> bool { return !m.empty(); }, + "Check whether the map is nonempty" + ); + + cl.def("__iter__", + [](Map &m) { return pybind11::make_key_iterator(m.begin(), m.end()); }, + pybind11::keep_alive<0, 1>() /* Essential: keep list alive while iterator exists */ + ); + + cl.def("items", + [](Map &m) { return pybind11::make_iterator(m.begin(), m.end()); }, + pybind11::keep_alive<0, 1>() /* Essential: keep list alive while iterator exists */ + ); + + cl.def("__getitem__", + [](Map &m, const KeyType &k) -> MappedType & { + auto it = m.find(k); + if (it == m.end()) + throw pybind11::key_error(); + return it->second; + }, + return_value_policy::reference_internal // ref + keepalive + ); + + // Assignment provided only if the type is copyable + detail::map_assignment<Map, Class_>(cl); + + cl.def("__delitem__", + [](Map &m, const KeyType &k) { + auto it = m.find(k); + if (it == m.end()) + throw pybind11::key_error(); + return m.erase(it); + } + ); + + cl.def("__len__", &Map::size); + + return cl; +} + +NAMESPACE_END(pybind11) diff --git a/ext/pybind11/include/pybind11/typeid.h b/ext/pybind11/include/pybind11/typeid.h new file mode 100644 index 000000000..c903fb14c --- /dev/null +++ b/ext/pybind11/include/pybind11/typeid.h @@ -0,0 +1,53 @@ +/* + pybind11/typeid.h: Compiler-independent access to type identifiers + + 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 <cstdio> +#include <cstdlib> + +#if defined(__GNUG__) +#include <cxxabi.h> +#endif + +NAMESPACE_BEGIN(pybind11) +NAMESPACE_BEGIN(detail) +/// Erase all occurrences of a substring +inline void erase_all(std::string &string, const std::string &search) { + for (size_t pos = 0;;) { + pos = string.find(search, pos); + if (pos == std::string::npos) break; + string.erase(pos, search.length()); + } +} + +PYBIND11_NOINLINE inline void clean_type_id(std::string &name) { +#if defined(__GNUG__) + int status = 0; + std::unique_ptr<char, void (*)(void *)> res { + abi::__cxa_demangle(name.c_str(), nullptr, nullptr, &status), std::free }; + if (status == 0) + name = res.get(); +#else + detail::erase_all(name, "class "); + detail::erase_all(name, "struct "); + detail::erase_all(name, "enum "); +#endif + detail::erase_all(name, "pybind11::"); +} +NAMESPACE_END(detail) + +/// Return a string representation of a C++ type +template <typename T> static std::string type_id() { + std::string name(typeid(T).name()); + detail::clean_type_id(name); + return name; +} + +NAMESPACE_END(pybind11) |