diff options
Diffstat (limited to 'ext/pybind11/include/pybind11/stl_bind.h')
-rw-r--r-- | ext/pybind11/include/pybind11/stl_bind.h | 82 |
1 files changed, 47 insertions, 35 deletions
diff --git a/ext/pybind11/include/pybind11/stl_bind.h b/ext/pybind11/include/pybind11/stl_bind.h index 897188220..7ef687878 100644 --- a/ext/pybind11/include/pybind11/stl_bind.h +++ b/ext/pybind11/include/pybind11/stl_bind.h @@ -9,13 +9,13 @@ #pragma once -#include "common.h" +#include "detail/common.h" #include "operators.h" #include <algorithm> #include <sstream> -NAMESPACE_BEGIN(pybind11) +NAMESPACE_BEGIN(PYBIND11_NAMESPACE) NAMESPACE_BEGIN(detail) /* SFINAE helper class used by 'is_comparable */ @@ -66,10 +66,7 @@ template <typename, typename, typename... Args> void vector_if_insertion_operato template <typename, typename, typename... Args> void vector_modifiers(const Args &...) { } template<typename Vector, typename Class_> -void vector_if_copy_constructible(enable_if_t< - std::is_copy_constructible<Vector>::value && - std::is_copy_constructible<typename Vector::value_type>::value, Class_> &cl) { - +void vector_if_copy_constructible(enable_if_t<is_copy_constructible<Vector>::value, Class_> &cl) { cl.def(init<const Vector &>(), "Copy constructor"); } @@ -113,7 +110,7 @@ void vector_if_equal_operator(enable_if_t<is_comparable<Vector>::value, Class_> // (Technically, some of these (pop and __delitem__) don't actually require copyability, but it seems // silly to allow deletion but not insertion, so include them here too.) template <typename Vector, typename Class_> -void vector_modifiers(enable_if_t<std::is_copy_constructible<typename Vector::value_type>::value, Class_> &cl) { +void vector_modifiers(enable_if_t<is_copy_constructible<typename Vector::value_type>::value, Class_> &cl) { using T = typename Vector::value_type; using SizeType = typename Vector::size_type; using DiffType = typename Vector::difference_type; @@ -123,21 +120,16 @@ void vector_modifiers(enable_if_t<std::is_copy_constructible<typename Vector::va arg("x"), "Add an item to the end of the list"); - cl.def("__init__", [](Vector &v, iterable it) { - new (&v) Vector(); - try { - v.reserve(len(it)); - for (handle h : it) - v.push_back(h.cast<T>()); - } catch (...) { - v.~Vector(); - throw; - } - }); + cl.def(init([](iterable it) { + auto v = std::unique_ptr<Vector>(new Vector()); + v->reserve(len(it)); + for (handle h : it) + v->push_back(h.cast<T>()); + return v.release(); + })); cl.def("extend", [](Vector &v, const Vector &src) { - v.reserve(v.size() + src.size()); v.insert(v.end(), src.begin(), src.end()); }, arg("L"), @@ -146,6 +138,8 @@ void vector_modifiers(enable_if_t<std::is_copy_constructible<typename Vector::va cl.def("insert", [](Vector &v, SizeType i, const T &x) { + if (i > v.size()) + throw index_error(); v.insert(v.begin() + (DiffType) i, x); }, arg("i") , arg("x"), @@ -345,23 +339,25 @@ vector_buffer(Class_& cl) { format_descriptor<T>::format(); cl.def_buffer([](Vector& v) -> buffer_info { - return buffer_info(v.data(), sizeof(T), format_descriptor<T>::format(), 1, {v.size()}, {sizeof(T)}); + return buffer_info(v.data(), static_cast<ssize_t>(sizeof(T)), format_descriptor<T>::format(), 1, {v.size()}, {sizeof(T)}); }); - cl.def("__init__", [](Vector& vec, buffer buf) { + cl.def(init([](buffer buf) { auto info = buf.request(); - if (info.ndim != 1 || info.strides[0] <= 0 || info.strides[0] % sizeof(T)) + if (info.ndim != 1 || info.strides[0] % static_cast<ssize_t>(sizeof(T))) throw type_error("Only valid 1D buffers can be copied to a vector"); - if (!detail::compare_buffer_info<T>::compare(info) || sizeof(T) != info.itemsize) + if (!detail::compare_buffer_info<T>::compare(info) || (ssize_t) sizeof(T) != info.itemsize) throw type_error("Format mismatch (Python: " + info.format + " C++: " + format_descriptor<T>::format() + ")"); - new (&vec) Vector(); - vec.reserve(info.shape[0]); + + auto vec = std::unique_ptr<Vector>(new Vector()); + vec->reserve((size_t) info.shape[0]); T *p = static_cast<T*>(info.ptr); - auto step = info.strides[0] / sizeof(T); + ssize_t step = info.strides[0] / static_cast<ssize_t>(sizeof(T)); T *end = p + info.shape[0] * step; - for (; p < end; p += step) - vec.push_back(*p); - }); + for (; p != end; p += step) + vec->push_back(*p); + return vec.release(); + })); return; } @@ -375,10 +371,16 @@ NAMESPACE_END(detail) // std::vector // template <typename Vector, typename holder_type = std::unique_ptr<Vector>, typename... Args> -class_<Vector, holder_type> bind_vector(module &m, std::string const &name, Args&&... args) { +class_<Vector, holder_type> bind_vector(handle scope, std::string const &name, Args&&... args) { using Class_ = class_<Vector, holder_type>; - Class_ cl(m, name.c_str(), std::forward<Args>(args)...); + // If the value_type is unregistered (e.g. a converting type) or is itself registered + // module-local then make the vector binding module-local as well: + using vtype = typename Vector::value_type; + auto vtype_info = detail::get_type_info(typeid(vtype)); + bool local = !vtype_info || vtype_info->module_local; + + Class_ cl(scope, name.c_str(), pybind11::module_local(local), std::forward<Args>(args)...); // Declare the buffer interface if a buffer_protocol() is passed in detail::vector_buffer<Vector, Class_, Args...>(cl); @@ -486,7 +488,7 @@ void map_assignment(enable_if_t<std::is_copy_assignable<typename Map::mapped_typ template<typename Map, typename Class_> void map_assignment(enable_if_t< !std::is_copy_assignable<typename Map::mapped_type>::value && - std::is_copy_constructible<typename Map::mapped_type>::value, + is_copy_constructible<typename Map::mapped_type>::value, Class_> &cl) { using KeyType = typename Map::key_type; using MappedType = typename Map::mapped_type; @@ -530,12 +532,22 @@ template <typename Map, typename Class_> auto map_if_insertion_operator(Class_ & NAMESPACE_END(detail) template <typename Map, typename holder_type = std::unique_ptr<Map>, typename... Args> -class_<Map, holder_type> bind_map(module &m, const std::string &name, Args&&... args) { +class_<Map, holder_type> bind_map(handle scope, const std::string &name, Args&&... args) { using KeyType = typename Map::key_type; using MappedType = typename Map::mapped_type; using Class_ = class_<Map, holder_type>; - Class_ cl(m, name.c_str(), std::forward<Args>(args)...); + // If either type is a non-module-local bound type then make the map binding non-local as well; + // otherwise (e.g. both types are either module-local or converting) the map will be + // module-local. + auto tinfo = detail::get_type_info(typeid(MappedType)); + bool local = !tinfo || tinfo->module_local; + if (local) { + tinfo = detail::get_type_info(typeid(KeyType)); + local = !tinfo || tinfo->module_local; + } + + Class_ cl(scope, name.c_str(), pybind11::module_local(local), std::forward<Args>(args)...); cl.def(init<>()); @@ -584,4 +596,4 @@ class_<Map, holder_type> bind_map(module &m, const std::string &name, Args&&... return cl; } -NAMESPACE_END(pybind11) +NAMESPACE_END(PYBIND11_NAMESPACE) |