mirror of
https://github.com/pybind/pybind11.git
synced 2026-05-12 09:17:42 +00:00
Merge branch 'master' into sh_merge_master
This commit is contained in:
@@ -12,6 +12,8 @@
|
||||
|
||||
#include "cast.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||
|
||||
/// \addtogroup annotations
|
||||
@@ -79,6 +81,23 @@ struct metaclass {
|
||||
explicit metaclass(handle value) : value(value) { }
|
||||
};
|
||||
|
||||
/// Specifies a custom callback with signature `void (PyHeapTypeObject*)` that
|
||||
/// may be used to customize the Python type.
|
||||
///
|
||||
/// The callback is invoked immediately before `PyType_Ready`.
|
||||
///
|
||||
/// Note: This is an advanced interface, and uses of it may require changes to
|
||||
/// work with later versions of pybind11. You may wish to consult the
|
||||
/// implementation of `make_new_python_type` in `detail/classes.h` to understand
|
||||
/// the context in which the callback will be run.
|
||||
struct custom_type_setup {
|
||||
using callback = std::function<void(PyHeapTypeObject *heap_type)>;
|
||||
|
||||
explicit custom_type_setup(callback value) : value(std::move(value)) {}
|
||||
|
||||
callback value;
|
||||
};
|
||||
|
||||
/// Annotation that marks a class as local to the module:
|
||||
struct module_local { const bool value;
|
||||
constexpr explicit module_local(bool v = true) : value(v) {}
|
||||
@@ -272,6 +291,9 @@ struct type_record {
|
||||
/// Custom metaclass (optional)
|
||||
handle metaclass;
|
||||
|
||||
/// Custom type setup.
|
||||
custom_type_setup::callback custom_type_setup_callback;
|
||||
|
||||
/// Multiple inheritance marker
|
||||
bool multiple_inheritance : 1;
|
||||
|
||||
@@ -476,6 +498,13 @@ struct process_attribute<dynamic_attr> : process_attribute_default<dynamic_attr>
|
||||
static void init(const dynamic_attr &, type_record *r) { r->dynamic_attr = true; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct process_attribute<custom_type_setup> {
|
||||
static void init(const custom_type_setup &value, type_record *r) {
|
||||
r->custom_type_setup_callback = value.value;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct process_attribute<is_final> : process_attribute_default<is_final> {
|
||||
static void init(const is_final &, type_record *r) { r->is_final = true; }
|
||||
|
||||
@@ -685,11 +685,13 @@ inline PyObject* make_new_python_type(const type_record &rec) {
|
||||
if (rec.buffer_protocol)
|
||||
enable_buffer_protocol(heap_type);
|
||||
|
||||
if (rec.custom_type_setup_callback)
|
||||
rec.custom_type_setup_callback(heap_type);
|
||||
|
||||
if (PyType_Ready(type) < 0)
|
||||
pybind11_fail(std::string(rec.name) + ": PyType_Ready failed (" + error_string() + ")!");
|
||||
|
||||
assert(rec.dynamic_attr ? PyType_HasFeature(type, Py_TPFLAGS_HAVE_GC)
|
||||
: !PyType_HasFeature(type, Py_TPFLAGS_HAVE_GC));
|
||||
assert(!rec.dynamic_attr || PyType_HasFeature(type, Py_TPFLAGS_HAVE_GC));
|
||||
|
||||
/* Register type with the parent scope */
|
||||
if (rec.scope)
|
||||
|
||||
@@ -85,12 +85,13 @@ inline PyObject *make_object_base_type(PyTypeObject *metaclass);
|
||||
// On CPython < 3.4 and on PyPy, `PyThread_set_key_value` strangely does not set
|
||||
// the value if it has already been set. Instead, it must first be deleted and
|
||||
// then set again.
|
||||
inline void tls_replace_value(PYBIND11_TLS_KEY_REF key, void *value) {
|
||||
PyThread_delete_key_value(key);
|
||||
PyThread_set_key_value(key, value);
|
||||
}
|
||||
# define PYBIND11_TLS_DELETE_VALUE(key) PyThread_delete_key_value(key)
|
||||
# define PYBIND11_TLS_REPLACE_VALUE(key, value) \
|
||||
do { \
|
||||
PyThread_delete_key_value((key)); \
|
||||
PyThread_set_key_value((key), (value)); \
|
||||
} while (false)
|
||||
::pybind11::detail::tls_replace_value((key), (value))
|
||||
# else
|
||||
# define PYBIND11_TLS_DELETE_VALUE(key) PyThread_set_key_value((key), nullptr)
|
||||
# define PYBIND11_TLS_REPLACE_VALUE(key, value) PyThread_set_key_value((key), (value))
|
||||
|
||||
@@ -2069,25 +2069,54 @@ inline std::pair<decltype(internals::registered_types_py)::iterator, bool> all_t
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Sentinel, bool KeyIterator, return_value_policy Policy>
|
||||
/* There are a large number of apparently unused template arguments because
|
||||
* each combination requires a separate py::class_ registration.
|
||||
*/
|
||||
template <typename Access, return_value_policy Policy, typename Iterator, typename Sentinel, typename ValueType, typename... Extra>
|
||||
struct iterator_state {
|
||||
Iterator it;
|
||||
Sentinel end;
|
||||
bool first_or_done;
|
||||
};
|
||||
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
// Note: these helpers take the iterator by non-const reference because some
|
||||
// iterators in the wild can't be dereferenced when const. C++ needs the extra parens in decltype
|
||||
// to enforce an lvalue. The & after Iterator is required for MSVC < 16.9. SFINAE cannot be
|
||||
// reused for result_type due to bugs in ICC, NVCC, and PGI compilers. See PR #3293.
|
||||
template <typename Iterator, typename SFINAE = decltype((*std::declval<Iterator &>()))>
|
||||
struct iterator_access {
|
||||
using result_type = decltype((*std::declval<Iterator &>()));
|
||||
// NOLINTNEXTLINE(readability-const-return-type) // PR #3263
|
||||
result_type operator()(Iterator &it) const {
|
||||
return *it;
|
||||
}
|
||||
};
|
||||
|
||||
/// Makes a python iterator from a first and past-the-end C++ InputIterator.
|
||||
template <return_value_policy Policy = return_value_policy::reference_internal,
|
||||
template <typename Iterator, typename SFINAE = decltype(((*std::declval<Iterator &>()).first)) >
|
||||
struct iterator_key_access {
|
||||
using result_type = decltype(((*std::declval<Iterator &>()).first));
|
||||
result_type operator()(Iterator &it) const {
|
||||
return (*it).first;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Iterator, typename SFINAE = decltype(((*std::declval<Iterator &>()).second))>
|
||||
struct iterator_value_access {
|
||||
using result_type = decltype(((*std::declval<Iterator &>()).second));
|
||||
result_type operator()(Iterator &it) const {
|
||||
return (*it).second;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Access,
|
||||
return_value_policy Policy,
|
||||
typename Iterator,
|
||||
typename Sentinel,
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS // Issue in breathe 4.26.1
|
||||
typename ValueType = decltype(*std::declval<Iterator>()),
|
||||
#endif
|
||||
typename ValueType,
|
||||
typename... Extra>
|
||||
iterator make_iterator(Iterator first, Sentinel last, Extra &&... extra) {
|
||||
using state = detail::iterator_state<Iterator, Sentinel, false, Policy>;
|
||||
iterator make_iterator_impl(Iterator first, Sentinel last, Extra &&... extra) {
|
||||
using state = detail::iterator_state<Access, Policy, Iterator, Sentinel, ValueType, Extra...>;
|
||||
// TODO: state captures only the types of Extra, not the values
|
||||
|
||||
if (!detail::get_type_info(typeid(state), false)) {
|
||||
class_<state>(handle(), "iterator", pybind11::module_local())
|
||||
@@ -2101,7 +2130,7 @@ iterator make_iterator(Iterator first, Sentinel last, Extra &&... extra) {
|
||||
s.first_or_done = true;
|
||||
throw stop_iteration();
|
||||
}
|
||||
return *s.it;
|
||||
return Access()(s.it);
|
||||
// NOLINTNEXTLINE(readability-const-return-type) // PR #3263
|
||||
}, std::forward<Extra>(extra)..., Policy);
|
||||
}
|
||||
@@ -2109,35 +2138,55 @@ iterator make_iterator(Iterator first, Sentinel last, Extra &&... extra) {
|
||||
return cast(state{first, last, true});
|
||||
}
|
||||
|
||||
/// Makes an python iterator over the keys (`.first`) of a iterator over pairs from a
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
|
||||
/// Makes a python iterator from a first and past-the-end C++ InputIterator.
|
||||
template <return_value_policy Policy = return_value_policy::reference_internal,
|
||||
typename Iterator,
|
||||
typename Sentinel,
|
||||
typename ValueType = typename detail::iterator_access<Iterator>::result_type,
|
||||
typename... Extra>
|
||||
iterator make_iterator(Iterator first, Sentinel last, Extra &&... extra) {
|
||||
return detail::make_iterator_impl<
|
||||
detail::iterator_access<Iterator>,
|
||||
Policy,
|
||||
Iterator,
|
||||
Sentinel,
|
||||
ValueType,
|
||||
Extra...>(first, last, std::forward<Extra>(extra)...);
|
||||
}
|
||||
|
||||
/// Makes a python iterator over the keys (`.first`) of a iterator over pairs from a
|
||||
/// first and past-the-end InputIterator.
|
||||
template <return_value_policy Policy = return_value_policy::reference_internal,
|
||||
typename Iterator,
|
||||
typename Sentinel,
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS // Issue in breathe 4.26.1
|
||||
typename KeyType = decltype((*std::declval<Iterator>()).first),
|
||||
#endif
|
||||
typename KeyType = typename detail::iterator_key_access<Iterator>::result_type,
|
||||
typename... Extra>
|
||||
iterator make_key_iterator(Iterator first, Sentinel last, Extra &&...extra) {
|
||||
using state = detail::iterator_state<Iterator, Sentinel, true, Policy>;
|
||||
return detail::make_iterator_impl<
|
||||
detail::iterator_key_access<Iterator>,
|
||||
Policy,
|
||||
Iterator,
|
||||
Sentinel,
|
||||
KeyType,
|
||||
Extra...>(first, last, std::forward<Extra>(extra)...);
|
||||
}
|
||||
|
||||
if (!detail::get_type_info(typeid(state), false)) {
|
||||
class_<state>(handle(), "iterator", pybind11::module_local())
|
||||
.def("__iter__", [](state &s) -> state& { return s; })
|
||||
.def("__next__", [](state &s) -> detail::remove_cv_t<KeyType> {
|
||||
if (!s.first_or_done)
|
||||
++s.it;
|
||||
else
|
||||
s.first_or_done = false;
|
||||
if (s.it == s.end) {
|
||||
s.first_or_done = true;
|
||||
throw stop_iteration();
|
||||
}
|
||||
return (*s.it).first;
|
||||
}, std::forward<Extra>(extra)..., Policy);
|
||||
}
|
||||
|
||||
return cast(state{first, last, true});
|
||||
/// Makes a python iterator over the values (`.second`) of a iterator over pairs from a
|
||||
/// first and past-the-end InputIterator.
|
||||
template <return_value_policy Policy = return_value_policy::reference_internal,
|
||||
typename Iterator,
|
||||
typename Sentinel,
|
||||
typename ValueType = typename detail::iterator_value_access<Iterator>::result_type,
|
||||
typename... Extra>
|
||||
iterator make_value_iterator(Iterator first, Sentinel last, Extra &&...extra) {
|
||||
return detail::make_iterator_impl<
|
||||
detail::iterator_value_access<Iterator>,
|
||||
Policy, Iterator,
|
||||
Sentinel,
|
||||
ValueType,
|
||||
Extra...>(first, last, std::forward<Extra>(extra)...);
|
||||
}
|
||||
|
||||
/// Makes an iterator over values of an stl container or other container supporting
|
||||
@@ -2154,6 +2203,13 @@ template <return_value_policy Policy = return_value_policy::reference_internal,
|
||||
return make_key_iterator<Policy>(std::begin(value), std::end(value), extra...);
|
||||
}
|
||||
|
||||
/// Makes an iterator over the values (`.second`) of a stl map-like container supporting
|
||||
/// `std::begin()`/`std::end()`
|
||||
template <return_value_policy Policy = return_value_policy::reference_internal,
|
||||
typename Type, typename... Extra> iterator make_value_iterator(Type &value, Extra&&... extra) {
|
||||
return make_value_iterator<Policy>(std::begin(value), std::end(value), extra...);
|
||||
}
|
||||
|
||||
template <typename InputType, typename OutputType> void implicitly_convertible() {
|
||||
struct set_flag {
|
||||
bool &flag;
|
||||
|
||||
@@ -259,8 +259,11 @@ public:
|
||||
|
||||
object& operator=(const object &other) {
|
||||
other.inc_ref();
|
||||
dec_ref();
|
||||
// Use temporary variable to ensure `*this` remains valid while
|
||||
// `Py_XDECREF` executes, in case `*this` is accessible from Python.
|
||||
handle temp(m_ptr);
|
||||
m_ptr = other.m_ptr;
|
||||
temp.dec_ref();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user