|
33 | 33 | #endif
|
34 | 34 |
|
35 | 35 | NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
| 36 | + |
| 37 | +class gil_scoped_acquire; |
| 38 | +class gil_scoped_release; |
| 39 | + |
36 | 40 | NAMESPACE_BEGIN(detail)
|
37 | 41 |
|
38 | 42 | /// A life support system for temporary objects created by `type_caster::load()`.
|
@@ -1510,9 +1514,55 @@ struct copyable_holder_caster : public type_caster_base<type> {
|
1510 | 1514 | holder_type holder;
|
1511 | 1515 | };
|
1512 | 1516 |
|
| 1517 | +/// Shared object crash fix: https://github.com/pybind/pybind11/issues/1546#issuecomment-526712704 |
| 1518 | + |
| 1519 | +// /// Specialize for the common std::shared_ptr, so users don't need to |
| 1520 | +// template <typename T> |
| 1521 | +// class type_caster<std::shared_ptr<T>> : public copyable_holder_caster<T, std::shared_ptr<T>> { }; |
| 1522 | + |
1513 | 1523 | /// Specialize for the common std::shared_ptr, so users don't need to
|
1514 | 1524 | template <typename T>
|
1515 |
| -class type_caster<std::shared_ptr<T>> : public copyable_holder_caster<T, std::shared_ptr<T>> { }; |
| 1525 | +class type_caster<std::shared_ptr<T>> { |
| 1526 | + |
| 1527 | + PYBIND11_TYPE_CASTER (std::shared_ptr<T>, _(PYBIND11_STRING_NAME)); |
| 1528 | + |
| 1529 | + using BaseCaster = copyable_holder_caster<T, std::shared_ptr<T>>; |
| 1530 | + |
| 1531 | + bool load (pybind11::handle src, bool b) |
| 1532 | + { |
| 1533 | + BaseCaster bc; |
| 1534 | + bool success = bc.load (src, b); |
| 1535 | + if (!success) |
| 1536 | + { |
| 1537 | + return false; |
| 1538 | + } |
| 1539 | + |
| 1540 | + auto base_ptr = static_cast<std::shared_ptr<T>> (bc); |
| 1541 | + auto h = BaseCaster::cast(base_ptr, return_value_policy(), handle()); |
| 1542 | + auto py_obj = reinterpret_borrow<object>(h); |
| 1543 | + |
| 1544 | + auto py_obj_ptr = std::shared_ptr<object>{ |
| 1545 | + new object{py_obj}, |
| 1546 | + [](auto py_object_ptr) { |
| 1547 | + // It's possible that when the shared_ptr dies we won't have the |
| 1548 | + // gil (if the last holder is in a non-Python thread), so we |
| 1549 | + // make sure to acquire it in the deleter. |
| 1550 | + gil_scoped_acquire gil; |
| 1551 | + delete py_object_ptr; |
| 1552 | + } |
| 1553 | + }; |
| 1554 | + |
| 1555 | + value = std::shared_ptr<T> (py_obj_ptr, base_ptr.get ()); |
| 1556 | + return true; |
| 1557 | + } |
| 1558 | + |
| 1559 | + static handle cast (std::shared_ptr<T> sp, |
| 1560 | + return_value_policy rvp, |
| 1561 | + handle h) |
| 1562 | + { |
| 1563 | + return BaseCaster::cast (sp, rvp, h); |
| 1564 | + } |
| 1565 | +}; |
1516 | 1566 |
|
1517 | 1567 | template <typename type, typename holder_type>
|
1518 | 1568 | struct move_only_holder_caster {
|
@@ -1554,6 +1604,11 @@ template <typename base, typename holder> struct is_holder_type :
|
1554 | 1604 | template <typename base, typename deleter> struct is_holder_type<base, std::unique_ptr<base, deleter>> :
|
1555 | 1605 | std::true_type {};
|
1556 | 1606 |
|
| 1607 | +// Specialization for shared_ptr: |
| 1608 | +template <typename base> struct is_holder_type<base, std::shared_ptr<base>> : |
| 1609 | + std::true_type {}; |
| 1610 | + |
| 1611 | + |
1557 | 1612 | template <typename T> struct handle_type_name { static constexpr auto name = _<T>(); };
|
1558 | 1613 | template <> struct handle_type_name<bytes> { static constexpr auto name = _(PYBIND11_BYTES_NAME); };
|
1559 | 1614 | template <> struct handle_type_name<args> { static constexpr auto name = _("*args"); };
|
@@ -1901,7 +1956,7 @@ class argument_loader {
|
1901 | 1956 | static constexpr bool has_kwargs = kwargs_pos < 0;
|
1902 | 1957 | static constexpr bool has_args = args_pos < 0;
|
1903 | 1958 |
|
1904 |
| - static constexpr auto arg_names = detail::concat(type_descr(make_caster<Args>::name)...); |
| 1959 | + static constexpr auto arg_names = concat(type_descr(make_caster<Args>::name)...); |
1905 | 1960 |
|
1906 | 1961 | bool load_args(function_call &call) {
|
1907 | 1962 | return load_impl_sequence(call, indices{});
|
|
0 commit comments