Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-04 09:20:03

0001 /*
0002     pybind11/detail/holder_caster_foreign_helpers.h: Logic to implement
0003     set_foreign_holder() in copyable_ and movable_holder_caster.
0004 
0005     Copyright (c) 2025 Hudson River Trading LLC <opensource@hudson-trading.com>
0006 
0007     All rights reserved. Use of this source code is governed by a
0008     BSD-style license that can be found in the LICENSE file.
0009 */
0010 
0011 #pragma once
0012 
0013 #include <pybind11/gil.h>
0014 
0015 #include "common.h"
0016 
0017 PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
0018 PYBIND11_NAMESPACE_BEGIN(detail)
0019 
0020 struct holder_caster_foreign_helpers {
0021     struct py_deleter {
0022         void operator()(const void *) const noexcept {
0023             // Don't run the deleter if the interpreter has been shut down
0024             if (Py_IsInitialized() == 0) {
0025                 return;
0026             }
0027             gil_scoped_acquire guard;
0028             Py_DECREF(o);
0029         }
0030 
0031         PyObject *o;
0032     };
0033 
0034     template <typename type>
0035     static auto set_via_shared_from_this(type *value, std::shared_ptr<type> *holder_out)
0036         -> decltype(value->shared_from_this(), bool()) {
0037         // object derives from enable_shared_from_this;
0038         // try to reuse an existing shared_ptr if one is known
0039         if (auto existing = try_get_shared_from_this(value)) {
0040             *holder_out = std::static_pointer_cast<type>(existing);
0041             return true;
0042         }
0043         return false;
0044     }
0045 
0046     template <typename type>
0047     static bool set_via_shared_from_this(void *, std::shared_ptr<type> *) {
0048         return false;
0049     }
0050 
0051     template <typename type>
0052     static bool set_foreign_holder(handle src, type *value, std::shared_ptr<type> *holder_out) {
0053         // We only support using std::shared_ptr<T> for foreign T, and
0054         // it's done by creating a new shared_ptr control block that
0055         // owns a reference to the original Python object.
0056         if (value == nullptr) {
0057             *holder_out = {};
0058             return true;
0059         }
0060         if (set_via_shared_from_this(value, holder_out)) {
0061             return true;
0062         }
0063         *holder_out = std::shared_ptr<type>(value, py_deleter{src.inc_ref().ptr()});
0064         return true;
0065     }
0066 
0067     template <typename type>
0068     static bool
0069     set_foreign_holder(handle src, const type *value, std::shared_ptr<const type> *holder_out) {
0070         std::shared_ptr<type> holder_mut;
0071         if (set_foreign_holder(src, const_cast<type *>(value), &holder_mut)) {
0072             *holder_out = holder_mut;
0073             return true;
0074         }
0075         return false;
0076     }
0077 
0078     template <typename type>
0079     static bool set_foreign_holder(handle, type *, ...) {
0080         throw cast_error("Unable to cast foreign type to held instance -- "
0081                          "only std::shared_ptr<T> is supported in this case");
0082     }
0083 };
0084 
0085 PYBIND11_NAMESPACE_END(detail)
0086 PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)