12 #include "../pytypes.h" 22 #include <type_traits> 25 #include <unordered_map> 39 #if defined(WITH_THREAD) 42 # if PYBIND11_INTERNALS_VERSION == 4 74 for (
auto *item : keep_alive) {
88 throw cast_error(
"When called outside a bound function, py::cast() cannot " 89 "do Python -> C++ conversions which require the creation " 90 "of temporary values");
102 inline std::pair<decltype(internals::registered_types_py)::iterator, bool>
107 std::vector<PyTypeObject *>
check;
108 for (
handle parent : reinterpret_borrow<tuple>(t->tp_bases)) {
109 check.push_back((PyTypeObject *)
parent.ptr());
113 for (
size_t i = 0;
i < check.size();
i++) {
114 auto *
type = check[
i];
116 if (!PyType_Check((PyObject *)
type)) {
121 auto it = type_dict.find(type);
122 if (it != type_dict.end()) {
127 for (
auto *tinfo : it->second) {
132 for (
auto *known : bases) {
133 if (known == tinfo) {
139 bases.push_back(tinfo);
142 }
else if (type->tp_bases) {
145 if (
i + 1 == check.size()) {
152 for (
handle parent : reinterpret_borrow<tuple>(type->tp_bases)) {
153 check.push_back((PyTypeObject *)
parent.ptr());
176 return ins.first->second;
189 if (bases.size() > 1) {
191 "pybind11::detail::get_type_info: type has multiple pybind11-registered bases");
193 return bases.front();
198 auto it = locals.find(tp);
199 if (it != locals.end()) {
207 auto it = types.find(tp);
208 if (it != types.end()) {
217 bool throw_if_missing =
false) {
225 if (throw_if_missing) {
226 std::string tname = tp.name();
228 pybind11_fail(
"pybind11::detail::get_type_info: unable to find type info for \"" 229 + std::move(tname) +
'"');
236 return handle(type_info ? ((PyObject *) type_info->type) :
nullptr);
241 const detail::type_info *tinfo) {
243 for (
auto it_i = it_instances.first; it_i != it_instances.second; ++it_i) {
245 if (instance_type &&
same_type(*instance_type->cpptype, *tinfo->cpptype)) {
256 const detail::type_info *
type =
nullptr;
271 template <
typename V =
void>
273 return reinterpret_cast<V *&
>(vh[0]);
276 explicit operator bool()
const {
return value_ptr() !=
nullptr; }
278 template <
typename H>
280 return reinterpret_cast<H &
>(vh[1]);
332 : inst{inst}, types{tinfo},
334 types->empty() ? nullptr : (*types)[0] ,
345 curr.
vh += 1 + (*types)[curr.
index]->holder_size_in_ptrs;
348 curr.
type = curr.
index < types->size() ? (*types)[curr.
index] :
nullptr;
360 while (it != endit && it->type != find_type) {
366 size_t size() {
return tinfo.size(); }
381 bool throw_if_missing ) {
383 if (!find_type || Py_TYPE(
this) == find_type->
type) {
387 detail::values_and_holders vhs(
this);
388 auto it = vhs.find(find_type);
389 if (it != vhs.end()) {
393 if (!throw_if_missing) {
397 #if defined(PYBIND11_DETAILED_ERROR_MESSAGES) 398 pybind11_fail(
"pybind11::detail::instance::get_value_and_holder: `" 400 +
"' is not a pybind11 base of the given `" 404 "pybind11::detail::instance::get_value_and_holder: " 405 "type is not a pybind11 base of the given instance " 406 "(#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for type details)");
413 const size_t n_types =
tinfo.size();
417 "instance allocation failed: new instance has no pybind11-registered base types");
425 simple_value_holder[0] =
nullptr;
426 simple_holder_constructed =
false;
427 simple_instance_registered =
false;
436 space +=
t->holder_size_in_ptrs;
438 size_t flags_at = space;
448 nonsimple.values_and_holders = (
void **) PyMem_Calloc(space,
sizeof(
void *));
449 if (!nonsimple.values_and_holders) {
450 throw std::bad_alloc();
453 =
reinterpret_cast<std::uint8_t *
>(&nonsimple.values_and_holders[flags_at]);
460 if (!simple_layout) {
461 PyMem_Free(nonsimple.values_and_holders);
475 auto range = instances.equal_range(ptr);
476 for (
auto it =
range.first; it !=
range.second; ++it) {
478 if (vh.type == type) {
479 return handle((PyObject *) it->second);
487 #if defined(PYPY_VERSION) 488 return PyThreadState_GET();
490 return _PyThreadState_UncheckedGet();
504 : typeinfo(typeinfo), cpptype(typeinfo ? typeinfo->cpptype : nullptr) {}
511 const detail::type_info *tinfo,
512 void *(*copy_constructor)(
const void *),
513 void *(*move_constructor)(
const void *),
514 const void *existing_holder =
nullptr) {
519 void *src =
const_cast<void *
>(_src);
520 if (src ==
nullptr) {
525 return registered_inst;
530 wrapper->
owned =
false;
537 wrapper->owned =
true;
543 wrapper->owned =
false;
547 if (copy_constructor) {
548 valueptr = copy_constructor(src);
550 #if defined(PYBIND11_DETAILED_ERROR_MESSAGES) 551 std::string
type_name(tinfo->cpptype->name());
553 throw cast_error(
"return_value_policy = copy, but type " +
type_name 554 +
" is non-copyable!");
556 throw cast_error(
"return_value_policy = copy, but type is " 557 "non-copyable! (#define PYBIND11_DETAILED_ERROR_MESSAGES or " 558 "compile in debug mode for details)");
561 wrapper->owned =
true;
565 if (move_constructor) {
566 valueptr = move_constructor(src);
567 }
else if (copy_constructor) {
568 valueptr = copy_constructor(src);
570 #if defined(PYBIND11_DETAILED_ERROR_MESSAGES) 571 std::string
type_name(tinfo->cpptype->name());
573 throw cast_error(
"return_value_policy = move, but type " +
type_name 574 +
" is neither movable nor copyable!");
576 throw cast_error(
"return_value_policy = move, but type is neither " 577 "movable nor copyable! " 578 "(#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in " 579 "debug mode for details)");
582 wrapper->owned =
true;
587 wrapper->owned =
false;
592 throw cast_error(
"unhandled return_value_policy: should not happen!");
595 tinfo->init_instance(wrapper, existing_holder);
597 return inst.release();
602 auto *&vptr = v_h.value_ptr();
604 if (vptr ==
nullptr) {
605 const auto *
type = v_h.type ? v_h.type : typeinfo;
606 if (
type->operator_new) {
607 vptr =
type->operator_new(
type->type_size);
609 #if defined(__cpp_aligned_new) && (!defined(_MSC_VER) || _MSC_VER >= 1912) 610 if (
type->type_align > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
611 vptr = ::operator
new(
type->type_size, std::align_val_t(
type->type_align));
613 vptr = ::operator
new(
type->type_size);
616 vptr = ::operator
new(
type->type_size);
623 for (
const auto &
cast : typeinfo->implicit_casts) {
625 if (sub_caster.
load(src, convert)) {
633 for (
auto &converter : *typeinfo->direct_conversions) {
644 if (caster.load(src,
false)) {
655 if (!
hasattr(pytype, local_key)) {
659 type_info *foreign_typeinfo = reinterpret_borrow<capsule>(
getattr(pytype, local_key));
677 template <
typename ThisT>
683 return try_load_foreign_module_local(src);
686 auto &this_ =
static_cast<ThisT &
>(*this);
687 this_.check_holder_compat();
689 PyTypeObject *srctype = Py_TYPE(src.
ptr());
693 if (srctype == typeinfo->type) {
694 this_.load_value(reinterpret_cast<instance *>(src.
ptr())->get_value_and_holder());
698 if (PyType_IsSubtype(srctype, typeinfo->type)) {
700 bool no_cpp_mi = typeinfo->simple_type;
708 if (bases.size() == 1 && (no_cpp_mi || bases.front()->type == typeinfo->type)) {
709 this_.load_value(reinterpret_cast<instance *>(src.
ptr())->get_value_and_holder());
715 if (bases.size() > 1) {
716 for (
auto *
base : bases) {
717 if (no_cpp_mi ? PyType_IsSubtype(
base->type, typeinfo->type)
718 :
base->type == typeinfo->type) {
720 reinterpret_cast<instance *>(src.
ptr())->get_value_and_holder(
base));
729 if (this_.try_implicit_casts(src, convert)) {
736 for (
const auto &converter : typeinfo->implicit_conversions) {
737 auto temp = reinterpret_steal<object>(converter(src.
ptr(), typeinfo->type));
738 if (load_impl<ThisT>(temp,
false)) {
743 if (this_.try_direct_conversions(src)) {
749 if (typeinfo->module_local) {
752 return load(src,
false);
757 if (try_load_foreign_module_local(src)) {
779 const std::type_info &cast_type,
780 const std::type_info *rtti_type =
nullptr) {
782 return {src,
const_cast<const type_info *
>(tpi)};
786 std::string tname = rtti_type ? rtti_type->name() : cast_type.name();
788 std::string
msg =
"Unregistered type : " + tname;
789 PyErr_SetString(PyExc_TypeError, msg.c_str());
790 return {
nullptr,
nullptr};
794 const std::type_info *cpptype =
nullptr;
805 template <
typename T>
807 typename std::add_pointer<intrinsic_t<T>>
::type,
808 typename std::add_lvalue_reference<intrinsic_t<T>>::type>;
817 template <
typename T>
820 typename std::add_pointer<intrinsic_t<T>>
::type,
822 typename std::add_rvalue_reference<intrinsic_t<T>>
::type,
823 typename std::add_lvalue_reference<intrinsic_t<T>>::type>>;
827 template <
typename T,
typename SFINAE =
void>
833 template <
typename Container>
838 std::is_same<typename Container::value_type &, typename Container::reference>,
840 negation<std::is_same<Container, typename Container::value_type>>>::value>>
847 template <
typename T1,
typename T2>
849 :
all_of<is_copy_constructible<T1>, is_copy_constructible<T2>> {};
852 template <
typename T,
typename SFINAE =
void>
854 template <
typename Container>
857 std::is_same<typename Container::value_type &,
858 typename Container::reference>>::value>>
860 template <
typename T1,
typename T2>
862 :
all_of<is_copy_assignable<T1>, is_copy_assignable<T2>> {};
887 template <
typename itype,
typename SFINAE =
void>
889 static const void *
get(
const itype *src,
const std::type_info *&) {
return src; }
891 template <
typename itype>
893 static const void *
get(
const itype *src,
const std::type_info *&
type) {
894 type = src ? &
typeid(*src) :
nullptr;
895 return dynamic_cast<const void *
>(src);
898 template <
typename itype,
typename SFINAE =
void>
903 template <
typename type>
909 static constexpr
auto name = const_name<type>();
919 return cast(&src, policy, parent);
930 const auto &cast_type =
typeid(
itype);
931 const std::type_info *instance_type =
nullptr;
933 if (instance_type && !
same_type(cast_type, *instance_type)) {
952 auto st = src_and_type(src);
957 make_copy_constructor(src),
958 make_move_constructor(src));
962 auto st = src_and_type(src);
972 template <
typename T>
980 throw reference_cast_error();
993 -> decltype(
new T(std::declval<const T>()),
Constructor{}) {
994 return [](
const void *
arg) ->
void * {
return new T(*reinterpret_cast<const T *>(
arg)); };
999 -> decltype(
new T(std::declval<T &&>()),
Constructor{}) {
1000 return [](
const void *
arg) ->
void * {
1001 return new T(std::move(*const_cast<T *>(reinterpret_cast<const T *>(
arg))));
typename std::conditional< B, T, F >::type conditional_t
PYBIND11_NOINLINE detail::type_info * get_type_info(PyTypeObject *type)
bool simple_holder_constructed
For simple layout, tracks whether the holder has been constructed.
static auto make_move_constructor(const T *) -> decltype(new T(std::declval< T &&>()), Constructor
void deallocate_layout()
Destroys/deallocates all of the above.
static constexpr uint8_t status_holder_constructed
Bit values for the non-simple status flags.
static auto make_copy_constructor(const T *) -> decltype(new T(std::declval< const T >()), Constructor
const detail::type_info * type
conditional_t< std::is_pointer< remove_reference_t< T > >::value, typename std::add_pointer< intrinsic_t< T > >::type, typename std::add_lvalue_reference< intrinsic_t< T > >::type > cast_op_type
static handle handle_of()
bool hasattr(handle obj, handle name)
value_and_holder(size_t index)
constexpr size_t instance_simple_holder_in_ptrs()
PYBIND11_NOINLINE handle get_object_handle(const void *ptr, const detail::type_info *type)
detail::cast_op_type< T > cast_op_type
static Constructor make_copy_constructor(...)
void set_holder_constructed(bool v=true)
bool load(handle src, bool convert)
static handle cast_holder(const itype *src, const void *holder)
std::vector< detail::type_info * > type_vec
void load_value(value_and_holder &&v_h)
void keep_alive_impl(handle nurse, handle patient)
PYBIND11_NOINLINE internals & get_internals()
Return a reference to the current internals data.
type_map< type_info * > registered_types_cpp
iterator(instance *inst, const type_vec *tinfo)
static constexpr size_t size_in_ptrs(size_t s)
PYBIND11_NOINLINE bool try_load_foreign_module_local(handle src)
void set_instance_registered(bool v=true)
set noclip points set clip one set noclip two set bar set border lt lw set xdata set ydata set zdata set x2data set y2data set boxwidth set dummy y set format x g set format y g set format x2 g set format y2 g set format z g set angles radians set nogrid set key title set key left top Right noreverse box linetype linewidth samplen spacing width set nolabel set noarrow set nologscale set logscale x set set pointsize set encoding default set nopolar set noparametric set set set set surface set nocontour set clabel set mapping cartesian set nohidden3d set cntrparam order set cntrparam linear set cntrparam levels auto set cntrparam points set size set set xzeroaxis lt lw set x2zeroaxis lt lw set yzeroaxis lt lw set y2zeroaxis lt lw set tics in set ticslevel set tics set mxtics default set mytics default set mx2tics default set my2tics default set xtics border mirror norotate autofreq set ytics border mirror norotate autofreq set ztics border nomirror norotate autofreq set nox2tics set noy2tics set timestamp bottom norotate set rrange [*:*] noreverse nowriteback set trange [*:*] noreverse nowriteback set urange [*:*] noreverse nowriteback set vrange [*:*] noreverse nowriteback set xlabel matrix size set x2label set timefmt d m y n H
std::unordered_multimap< const void *, instance * > registered_instances
bool isinstance(handle obj)
PYBIND11_NOINLINE handle get_type_handle(const std::type_info &tp, bool throw_if_missing)
static const void * get(const itype *src, const std::type_info *&)
#define PYBIND11_NAMESPACE
The 'instance' type which needs to be standard layout (need to be able to use 'offsetof') ...
void check_holder_compat()
PYBIND11_NOINLINE void clean_type_id(std::string &name)
std::pair< decltype(internals::registered_types_py)::iterator, bool > all_type_info_get_cache(PyTypeObject *type)
bool same_type(const std::type_info &lhs, const std::type_info &rhs)
static handle cast(itype &&src, return_value_policy, handle parent)
PyExc_RuntimeError [[noreturn]] PYBIND11_NOINLINE void pybind11_fail(const char *reason)
Used internally.
const handle & inc_ref() const &
value_and_holder get_value_and_holder(const type_info *find_type=nullptr, bool throw_if_missing=true)
static handle cast(const itype &src, return_value_policy policy, handle parent)
bool try_implicit_casts(handle src, bool convert)
void *(*)(const void *) Constructor
static constexpr uint8_t status_instance_registered
const std::type_info * cpptype
#define PYBIND11_TLS_KEY_REF
static loader_life_support ** get_stack_pp()
std::string get_fully_qualified_tp_name(PyTypeObject *type)
PYBIND11_NOINLINE bool isinstance_generic(handle obj, const std::type_info &tp)
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const ArgReturnType arg() const
Array< int, Dynamic, 1 > v
local_internals & get_local_internals()
Works like get_internals, but for things which are locally registered.
type_map< type_info * > registered_types_cpp
std::unordered_set< PyObject * > keep_alive
static void set_stack_top(loader_life_support *value)
EIGEN_DEVICE_FUNC NewType cast(const OldType &x)
Eigen::Triplet< double > T
static std::pair< const void *, const type_info * > src_and_type(const itype *src)
loader_life_support * parent
static handle cast(const itype *src, return_value_policy policy, handle parent)
conditional_t< std::is_pointer< typename std::remove_reference< T >::type >::value, typename std::add_pointer< intrinsic_t< T > >::type, conditional_t< std::is_rvalue_reference< T >::value, typename std::add_rvalue_reference< intrinsic_t< T > >::type, typename std::add_lvalue_reference< intrinsic_t< T > >::type > > movable_cast_op_type
bool operator==(const iterator &other) const
iterator find(const type_info *find_type)
~loader_life_support()
... and destroyed after it returns
value_and_holder(instance *i, const detail::type_info *type, size_t vpos, size_t index)
#define PYBIND11_MODULE_LOCAL_ID
bool owned
If true, the pointer is owned which means we're free to manage it with a holder.
std::is_same< bools< Ts::value..., true >, bools< true, Ts::value... > > all_of
loader_life_support()
A new patient frame is created when a function is entered.
type_caster_base(const std::type_info &info)
void check(bool b, bool ref)
bool try_direct_conversions(handle src)
void ** values_and_holders
detail::type_info * get_global_type_info(const std::type_index &tp)
bool holder_constructed() const
typename intrinsic_type< T >::type intrinsic_t
const std::vector< detail::type_info * > & all_type_info(PyTypeObject *type)
object getattr(handle obj, handle name)
#define PYBIND11_TLS_REPLACE_VALUE(key, value)
detail::type_info * get_local_type_info(const std::type_index &tp)
Double_ range(const Point2_ &p, const Point2_ &q)
static PYBIND11_NOINLINE handle cast(const void *_src, return_value_policy policy, handle parent, const detail::type_info *tinfo, void *(*copy_constructor)(const void *), void *(*move_constructor)(const void *), const void *existing_holder=nullptr)
bool simple_instance_registered
For simple layout, tracks whether the instance is registered in registered_instances ...
static EIGEN_DEPRECATED const end_t end
PYBIND11_NOINLINE type_caster_generic(const std::type_info &type_info)
PyThreadState * get_thread_state_unchecked()
Generic type caster for objects stored on the heap.
value_and_holder & operator*()
bool operator!=(const iterator &other) const
static PYBIND11_NOINLINE void * local_load(PyObject *src, const type_info *ti)
void * simple_value_holder[1+instance_simple_holder_in_ptrs()]
typename std::enable_if< B, T >::type enable_if_t
from cpp_future import (convenient aliases from C++14/17)
PYBIND11_NOINLINE handle find_registered_python_instance(void *src, const detail::type_info *tinfo)
Annotation for function names.
Annotation indicating that a class derives from another given type.
PyObject * ptr() const
Return the underlying PyObject * pointer.
#define PYBIND11_TLS_GET_VALUE(key)
std::unordered_map< PyTypeObject *, std::vector< type_info * > > registered_types_py
void *(* module_local_load)(PyObject *, const type_info *)
values_and_holders(instance *inst)
bool instance_registered() const
PYBIND11_NOINLINE void all_type_info_populate(PyTypeObject *t, std::vector< type_info *> &bases)
#define PYBIND11_NOINLINE
return_value_policy
Approach used to cast a previously unknown C++ instance into a Python object.
static PYBIND11_NOINLINE void add_patient(handle h)
nonsimple_values_and_holders nonsimple
PYBIND11_NOINLINE bool load_impl(handle src, bool convert)
static PYBIND11_NOINLINE std::pair< const void *, const type_info * > src_and_type(const void *src, const std::type_info &cast_type, const std::type_info *rtti_type=nullptr)
#define PYBIND11_NAMESPACE_END(name)
static BinaryMeasurement< Rot3 > convert(const BetweenFactor< Pose3 >::shared_ptr &f)
#define PYBIND11_NAMESPACE_BEGIN(name)
static loader_life_support * get_stack_top()
value_and_holder * operator->()
static Constructor make_move_constructor(...)
type_caster_generic(const type_info *typeinfo)
PyObject * make_new_instance(PyTypeObject *type)