// Copyright (c) 2024 The pybind Community. #pragma once #include #include "common.h" #include "internals.h" #include PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(detail) // Forward declaration needed here: Refactoring opportunity. extern "C" inline PyObject *pybind11_object_new(PyTypeObject *type, PyObject *, PyObject *); inline bool type_is_managed_by_our_internals(PyTypeObject *type_obj) { #if defined(PYPY_VERSION) auto &internals = get_internals(); return bool(internals.registered_types_py.find(type_obj) != internals.registered_types_py.end()); #else return bool(type_obj->tp_new == pybind11_object_new); #endif } inline bool is_instance_method_of_type(PyTypeObject *type_obj, PyObject *attr_name) { PyObject *descr = _PyType_Lookup(type_obj, attr_name); return bool((descr != nullptr) && PyInstanceMethod_Check(descr)); } inline object try_get_cpp_conduit_method(PyObject *obj) { if (PyType_Check(obj)) { return object(); } PyTypeObject *type_obj = Py_TYPE(obj); str attr_name("_pybind11_conduit_v1_"); bool assumed_to_be_callable = false; if (type_is_managed_by_our_internals(type_obj)) { if (!is_instance_method_of_type(type_obj, attr_name.ptr())) { return object(); } assumed_to_be_callable = true; } PyObject *method = PyObject_GetAttr(obj, attr_name.ptr()); if (method == nullptr) { PyErr_Clear(); return object(); } if (!assumed_to_be_callable && PyCallable_Check(method) == 0) { Py_DECREF(method); return object(); } return reinterpret_steal(method); } inline void *try_raw_pointer_ephemeral_from_cpp_conduit(handle src, const std::type_info *cpp_type_info) { object method = try_get_cpp_conduit_method(src.ptr()); if (method) { capsule cpp_type_info_capsule(const_cast(static_cast(cpp_type_info)), typeid(std::type_info).name()); object cpp_conduit = method(bytes(PYBIND11_PLATFORM_ABI_ID), cpp_type_info_capsule, bytes("raw_pointer_ephemeral")); if (isinstance(cpp_conduit)) { return reinterpret_borrow(cpp_conduit).get_pointer(); } } return nullptr; } #define PYBIND11_HAS_CPP_CONDUIT 1 PYBIND11_NAMESPACE_END(detail) PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)