mirror of
https://github.com/pybind/pybind11.git
synced 2026-05-12 09:17:42 +00:00
Allow references to objects held by smart pointers (#533)
This commit is contained in:
committed by
Wenzel Jakob
parent
8c85a85747
commit
ab90ec6ce9
@@ -860,20 +860,12 @@ public:
|
||||
|
||||
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)) {
|
||||
auto inst = (instance<type, holder_type> *) src.ptr();
|
||||
value = (void *) inst->value;
|
||||
holder = inst->holder;
|
||||
return true;
|
||||
}
|
||||
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) {
|
||||
auto inst = (instance<type, holder_type> *) src.ptr();
|
||||
value = (void *) inst->value;
|
||||
holder = inst->holder;
|
||||
return true;
|
||||
}
|
||||
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;
|
||||
@@ -902,6 +894,22 @@ public:
|
||||
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; }
|
||||
|
||||
|
||||
@@ -1138,21 +1138,26 @@ private:
|
||||
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 &) {
|
||||
new (&inst->holder) holder_type(inst->value);
|
||||
if (inst->owned) {
|
||||
new (&inst->holder) holder_type(inst->value);
|
||||
inst->holder_constructed = true;
|
||||
}
|
||||
}
|
||||
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)
|
||||
if (holder_ptr) {
|
||||
new (&inst->holder) holder_type(*holder_ptr);
|
||||
else
|
||||
inst->holder_constructed = true;
|
||||
} else if (inst->owned) {
|
||||
new (&inst->holder) holder_type(inst->value);
|
||||
inst->holder_constructed = true;
|
||||
inst->holder_constructed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialize holder object, variant 3: holder is not copy constructible (e.g. unique_ptr), always initialize from raw pointer
|
||||
|
||||
Reference in New Issue
Block a user