mirror of
https://github.com/pybind/pybind11.git
synced 2026-05-12 01:10:34 +00:00
Merge branch 'master' into smart_holder
This commit is contained in:
@@ -1586,7 +1586,7 @@ private:
|
||||
throw cast_error_unable_to_convert_call_arg(a.name, a.type);
|
||||
#endif
|
||||
}
|
||||
m_kwargs[a.name] = a.value;
|
||||
m_kwargs[a.name] = std::move(a.value);
|
||||
}
|
||||
|
||||
void process(list & /*args_list*/, detail::kwargs_proxy kp) {
|
||||
|
||||
@@ -1045,12 +1045,7 @@ PYBIND11_NAMESPACE_END(detail)
|
||||
/// - regular: static_cast<Return (Class::*)(Arg0, Arg1, Arg2)>(&Class::func)
|
||||
/// - sweet: overload_cast<Arg0, Arg1, Arg2>(&Class::func)
|
||||
template <typename... Args>
|
||||
# if (defined(_MSC_VER) && _MSC_VER < 1920) /* MSVC 2017 */ \
|
||||
|| (defined(__clang__) && __clang_major__ == 5)
|
||||
static constexpr detail::overload_cast_impl<Args...> overload_cast = {};
|
||||
# else
|
||||
static constexpr detail::overload_cast_impl<Args...> overload_cast;
|
||||
# endif
|
||||
static constexpr detail::overload_cast_impl<Args...> overload_cast{};
|
||||
#endif
|
||||
|
||||
/// Const member function selector for overload_cast
|
||||
|
||||
@@ -423,6 +423,8 @@ PYBIND11_NOINLINE internals &get_internals() {
|
||||
// Cannot use py::gil_scoped_acquire here since that constructor calls get_internals.
|
||||
struct gil_scoped_acquire_local {
|
||||
gil_scoped_acquire_local() : state(PyGILState_Ensure()) {}
|
||||
gil_scoped_acquire_local(const gil_scoped_acquire_local &) = delete;
|
||||
gil_scoped_acquire_local &operator=(const gil_scoped_acquire_local &) = delete;
|
||||
~gil_scoped_acquire_local() { PyGILState_Release(state); }
|
||||
const PyGILState_STATE state;
|
||||
} gil;
|
||||
@@ -523,8 +525,13 @@ struct local_internals {
|
||||
|
||||
/// Works like `get_internals`, but for things which are locally registered.
|
||||
inline local_internals &get_local_internals() {
|
||||
static local_internals locals;
|
||||
return locals;
|
||||
// Current static can be created in the interpreter finalization routine. If the later will be
|
||||
// destroyed in another static variable destructor, creation of this static there will cause
|
||||
// static deinitialization fiasco. In order to avoid it we avoid destruction of the
|
||||
// local_internals static. One can read more about the problem and current solution here:
|
||||
// https://google.github.io/styleguide/cppguide.html#Static_and_Global_Variables
|
||||
static auto *locals = new local_internals();
|
||||
return *locals;
|
||||
}
|
||||
|
||||
/// Constructs a std::string with the given arguments, stores it in `internals`, and returns its
|
||||
|
||||
@@ -80,6 +80,9 @@ public:
|
||||
inc_ref();
|
||||
}
|
||||
|
||||
gil_scoped_acquire(const gil_scoped_acquire &) = delete;
|
||||
gil_scoped_acquire &operator=(const gil_scoped_acquire &) = delete;
|
||||
|
||||
void inc_ref() { ++tstate->gilstate_counter; }
|
||||
|
||||
PYBIND11_NOINLINE void dec_ref() {
|
||||
@@ -144,6 +147,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
gil_scoped_release(const gil_scoped_acquire &) = delete;
|
||||
gil_scoped_release &operator=(const gil_scoped_acquire &) = delete;
|
||||
|
||||
/// This method will disable the PyThreadState_DeleteCurrent call and the
|
||||
/// GIL won't be acquired. This method should be used if the interpreter
|
||||
/// could be shutting down when this is called, as thread deletion is not
|
||||
@@ -178,6 +184,8 @@ class gil_scoped_acquire {
|
||||
|
||||
public:
|
||||
gil_scoped_acquire() { state = PyGILState_Ensure(); }
|
||||
gil_scoped_acquire(const gil_scoped_acquire &) = delete;
|
||||
gil_scoped_acquire &operator=(const gil_scoped_acquire &) = delete;
|
||||
~gil_scoped_acquire() { PyGILState_Release(state); }
|
||||
void disarm() {}
|
||||
};
|
||||
@@ -187,6 +195,8 @@ class gil_scoped_release {
|
||||
|
||||
public:
|
||||
gil_scoped_release() { state = PyEval_SaveThread(); }
|
||||
gil_scoped_release(const gil_scoped_release &) = delete;
|
||||
gil_scoped_release &operator=(const gil_scoped_acquire &) = delete;
|
||||
~gil_scoped_release() { PyEval_RestoreThread(state); }
|
||||
void disarm() {}
|
||||
};
|
||||
|
||||
@@ -84,6 +84,7 @@ struct op_impl {};
|
||||
/// Operator implementation generator
|
||||
template <op_id id, op_type ot, typename L, typename R>
|
||||
struct op_ {
|
||||
static constexpr bool op_enable_if_hook = true;
|
||||
template <typename Class, typename... Extra>
|
||||
void execute(Class &cl, const Extra &...extra) const {
|
||||
using Base = typename Class::type;
|
||||
|
||||
@@ -1808,14 +1808,14 @@ public:
|
||||
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) {
|
||||
template <typename T, typename... Extra, detail::enable_if_t<T::op_enable_if_hook, int> = 0>
|
||||
class_ &def(const T &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) {
|
||||
template <typename T, typename... Extra, detail::enable_if_t<T::op_enable_if_hook, int> = 0>
|
||||
class_ &def_cast(const T &op, const Extra &...extra) {
|
||||
op.execute_cast(*this, extra...);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -1829,18 +1829,18 @@ public:
|
||||
// guard if destructor called while err indicator is set
|
||||
error_scope error_guard;
|
||||
auto destructor = reinterpret_cast<void (*)(void *)>(PyCapsule_GetContext(o));
|
||||
if (destructor == nullptr) {
|
||||
if (PyErr_Occurred()) {
|
||||
throw error_already_set();
|
||||
}
|
||||
pybind11_fail("Unable to get capsule context");
|
||||
if (PyErr_Occurred()) {
|
||||
throw error_already_set();
|
||||
}
|
||||
const char *name = get_name_in_error_scope(o);
|
||||
void *ptr = PyCapsule_GetPointer(o, name);
|
||||
if (ptr == nullptr) {
|
||||
throw error_already_set();
|
||||
}
|
||||
destructor(ptr);
|
||||
|
||||
if (destructor != nullptr) {
|
||||
destructor(ptr);
|
||||
}
|
||||
});
|
||||
|
||||
if (!m_ptr || PyCapsule_SetContext(m_ptr, (void *) destructor) != 0) {
|
||||
@@ -2022,14 +2022,20 @@ public:
|
||||
detail::list_iterator end() const { return {*this, PyList_GET_SIZE(m_ptr)}; }
|
||||
template <typename T>
|
||||
void append(T &&val) /* py-non-const */ {
|
||||
PyList_Append(m_ptr, detail::object_or_cast(std::forward<T>(val)).ptr());
|
||||
if (PyList_Append(m_ptr, detail::object_or_cast(std::forward<T>(val)).ptr()) != 0) {
|
||||
throw error_already_set();
|
||||
}
|
||||
}
|
||||
template <typename IdxType,
|
||||
typename ValType,
|
||||
detail::enable_if_t<std::is_integral<IdxType>::value, int> = 0>
|
||||
void insert(const IdxType &index, ValType &&val) /* py-non-const */ {
|
||||
PyList_Insert(
|
||||
m_ptr, ssize_t_cast(index), detail::object_or_cast(std::forward<ValType>(val)).ptr());
|
||||
if (PyList_Insert(m_ptr,
|
||||
ssize_t_cast(index),
|
||||
detail::object_or_cast(std::forward<ValType>(val)).ptr())
|
||||
!= 0) {
|
||||
throw error_already_set();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -49,17 +49,31 @@ constexpr forwarded_type<T, U> forward_like(U &&u) {
|
||||
return std::forward<detail::forwarded_type<T, U>>(std::forward<U>(u));
|
||||
}
|
||||
|
||||
// Checks if a container has a STL style reserve method.
|
||||
// This will only return true for a `reserve()` with a `void` return.
|
||||
template <typename C>
|
||||
using has_reserve_method = std::is_same<decltype(std::declval<C>().reserve(0)), void>;
|
||||
|
||||
template <typename Type, typename Key>
|
||||
struct set_caster {
|
||||
using type = Type;
|
||||
using key_conv = make_caster<Key>;
|
||||
|
||||
private:
|
||||
template <typename T = Type, enable_if_t<has_reserve_method<T>::value, int> = 0>
|
||||
void reserve_maybe(const anyset &s, Type *) {
|
||||
value.reserve(s.size());
|
||||
}
|
||||
void reserve_maybe(const anyset &, void *) {}
|
||||
|
||||
public:
|
||||
bool load(handle src, bool convert) {
|
||||
if (!isinstance<anyset>(src)) {
|
||||
return false;
|
||||
}
|
||||
auto s = reinterpret_borrow<anyset>(src);
|
||||
value.clear();
|
||||
reserve_maybe(s, &value);
|
||||
for (auto entry : s) {
|
||||
key_conv conv;
|
||||
if (!conv.load(entry, convert)) {
|
||||
@@ -94,12 +108,21 @@ struct map_caster {
|
||||
using key_conv = make_caster<Key>;
|
||||
using value_conv = make_caster<Value>;
|
||||
|
||||
private:
|
||||
template <typename T = Type, enable_if_t<has_reserve_method<T>::value, int> = 0>
|
||||
void reserve_maybe(const dict &d, Type *) {
|
||||
value.reserve(d.size());
|
||||
}
|
||||
void reserve_maybe(const dict &, void *) {}
|
||||
|
||||
public:
|
||||
bool load(handle src, bool convert) {
|
||||
if (!isinstance<dict>(src)) {
|
||||
return false;
|
||||
}
|
||||
auto d = reinterpret_borrow<dict>(src);
|
||||
value.clear();
|
||||
reserve_maybe(d, &value);
|
||||
for (auto it : d) {
|
||||
key_conv kconv;
|
||||
value_conv vconv;
|
||||
@@ -160,9 +183,7 @@ struct list_caster {
|
||||
}
|
||||
|
||||
private:
|
||||
template <
|
||||
typename T = Type,
|
||||
enable_if_t<std::is_same<decltype(std::declval<T>().reserve(0)), void>::value, int> = 0>
|
||||
template <typename T = Type, enable_if_t<has_reserve_method<T>::value, int> = 0>
|
||||
void reserve_maybe(const sequence &s, Type *) {
|
||||
value.reserve(s.size());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user