Skip to content

Commit 2c7cc92

Browse files
Merge branch 'pybind:master' into master
2 parents 0a172df + ad9180c commit 2c7cc92

15 files changed

Lines changed: 199 additions & 109 deletions

docs/advanced/exceptions.rst

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,28 @@ Alternately, to ignore the error, call `PyErr_Clear
328328
Any Python error must be thrown or cleared, or Python/pybind11 will be left in
329329
an invalid state.
330330

331+
Handling warnings from the Python C API
332+
=======================================
333+
334+
Wrappers for handling Python warnings are provided in ``pybind11/warnings.h``.
335+
This header must be included explicitly; it is not transitively included via
336+
``pybind11/pybind11.h``.
337+
338+
Warnings can be raised with the ``warn`` function:
339+
340+
.. code-block:: cpp
341+
342+
py::warnings::warn("This is a warning!", PyExc_Warning);
343+
344+
// Optionally, a `stack_level` can be specified.
345+
py::warnings::warn("Another one!", PyExc_DeprecationWarning, 3);
346+
347+
New warning types can be registered at the module level using ``new_warning_type``:
348+
349+
.. code-block:: cpp
350+
351+
py::warnings::new_warning_type(m, "CustomWarning", PyExc_RuntimeWarning);
352+
331353
Chaining exceptions ('raise from')
332354
==================================
333355

include/pybind11/attr.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "detail/common.h"
1414
#include "cast.h"
15+
#include "trampoline_self_life_support.h"
1516

1617
#include <functional>
1718

@@ -312,6 +313,12 @@ struct type_record {
312313
/// Function pointer to class_<..>::dealloc
313314
void (*dealloc)(detail::value_and_holder &) = nullptr;
314315

316+
/// Function pointer for casting alias class (aka trampoline) pointer to
317+
/// trampoline_self_life_support pointer. Sidesteps cross-DSO RTTI issues
318+
/// on platforms like macOS (see PR #5728 for details).
319+
get_trampoline_self_life_support_fn get_trampoline_self_life_support
320+
= [](void *) -> trampoline_self_life_support * { return nullptr; };
321+
315322
/// List of base classes of the newly created type
316323
list bases;
317324

include/pybind11/cast.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -980,7 +980,7 @@ struct copyable_holder_caster<
980980

981981
explicit operator std::shared_ptr<type> &() {
982982
if (typeinfo->holder_enum_v == detail::holder_enum_t::smart_holder) {
983-
shared_ptr_storage = sh_load_helper.load_as_shared_ptr(value);
983+
shared_ptr_storage = sh_load_helper.load_as_shared_ptr(typeinfo, value);
984984
}
985985
return shared_ptr_storage;
986986
}
@@ -989,7 +989,8 @@ struct copyable_holder_caster<
989989
if (typeinfo->holder_enum_v == detail::holder_enum_t::smart_holder) {
990990
// Reusing shared_ptr code to minimize code complexity.
991991
shared_ptr_storage
992-
= sh_load_helper.load_as_shared_ptr(value,
992+
= sh_load_helper.load_as_shared_ptr(typeinfo,
993+
value,
993994
/*responsible_parent=*/nullptr,
994995
/*force_potentially_slicing_shared_ptr=*/true);
995996
}
@@ -1019,7 +1020,8 @@ struct copyable_holder_caster<
10191020
copyable_holder_caster loader;
10201021
loader.load(responsible_parent, /*convert=*/false);
10211022
assert(loader.typeinfo->holder_enum_v == detail::holder_enum_t::smart_holder);
1022-
return loader.sh_load_helper.load_as_shared_ptr(loader.value, responsible_parent);
1023+
return loader.sh_load_helper.load_as_shared_ptr(
1024+
loader.typeinfo, loader.value, responsible_parent);
10231025
}
10241026

10251027
protected:
@@ -1240,20 +1242,20 @@ struct move_only_holder_caster<
12401242

12411243
explicit operator std::unique_ptr<type, deleter>() {
12421244
if (typeinfo->holder_enum_v == detail::holder_enum_t::smart_holder) {
1243-
return sh_load_helper.template load_as_unique_ptr<deleter>(value);
1245+
return sh_load_helper.template load_as_unique_ptr<deleter>(typeinfo, value);
12441246
}
12451247
pybind11_fail("Expected to be UNREACHABLE: " __FILE__ ":" PYBIND11_TOSTRING(__LINE__));
12461248
}
12471249

12481250
explicit operator const std::unique_ptr<type, deleter> &() {
12491251
if (typeinfo->holder_enum_v == detail::holder_enum_t::smart_holder) {
12501252
// Get shared_ptr to ensure that the Python object is not disowned elsewhere.
1251-
shared_ptr_storage = sh_load_helper.load_as_shared_ptr(value);
1253+
shared_ptr_storage = sh_load_helper.load_as_shared_ptr(typeinfo, value);
12521254
// Build a temporary unique_ptr that is meant to never expire.
12531255
unique_ptr_storage = std::shared_ptr<std::unique_ptr<type, deleter>>(
12541256
new std::unique_ptr<type, deleter>{
12551257
sh_load_helper.template load_as_const_unique_ptr<deleter>(
1256-
shared_ptr_storage.get())},
1258+
typeinfo, shared_ptr_storage.get())},
12571259
[](std::unique_ptr<type, deleter> *ptr) {
12581260
if (!ptr) {
12591261
pybind11_fail("FATAL: `const std::unique_ptr<T, D> &` was disowned "

include/pybind11/detail/init.h

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -246,20 +246,38 @@ void construct(value_and_holder &v_h,
246246
v_h.type->init_instance(v_h.inst, &smhldr);
247247
}
248248

249-
template <typename Class, detail::enable_if_t<is_smart_holder<Holder<Class>>::value, int> = 0>
250-
void construct(value_and_holder &v_h, std::shared_ptr<Cpp<Class>> &&shd_ptr, bool need_alias) {
251-
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(need_alias);
249+
template <typename PtrType, typename Class>
250+
void construct_from_shared_ptr(value_and_holder &v_h,
251+
std::shared_ptr<PtrType> &&shd_ptr,
252+
bool need_alias) {
253+
static_assert(std::is_same<PtrType, Cpp<Class>>::value
254+
|| std::is_same<PtrType, const Cpp<Class>>::value,
255+
"Expected (const) Cpp<Class> as shared_ptr pointee");
252256
auto *ptr = shd_ptr.get();
253257
no_nullptr(ptr);
254258
if (Class::has_alias && need_alias && !is_alias<Class>(ptr)) {
255259
throw type_error("pybind11::init(): construction failed: returned std::shared_ptr pointee "
256260
"is not an alias instance");
257261
}
258-
auto smhldr = smart_holder::from_shared_ptr(shd_ptr);
259-
v_h.value_ptr() = ptr;
262+
// Cast to non-const if needed, consistent with internal design
263+
auto smhldr
264+
= smart_holder::from_shared_ptr(std::const_pointer_cast<Cpp<Class>>(std::move(shd_ptr)));
265+
v_h.value_ptr() = const_cast<Cpp<Class> *>(ptr);
260266
v_h.type->init_instance(v_h.inst, &smhldr);
261267
}
262268

269+
template <typename Class, detail::enable_if_t<is_smart_holder<Holder<Class>>::value, int> = 0>
270+
void construct(value_and_holder &v_h, std::shared_ptr<Cpp<Class>> &&shd_ptr, bool need_alias) {
271+
construct_from_shared_ptr<Cpp<Class>, Class>(v_h, std::move(shd_ptr), need_alias);
272+
}
273+
274+
template <typename Class, detail::enable_if_t<is_smart_holder<Holder<Class>>::value, int> = 0>
275+
void construct(value_and_holder &v_h,
276+
std::shared_ptr<const Cpp<Class>> &&shd_ptr,
277+
bool need_alias) {
278+
construct_from_shared_ptr<const Cpp<Class>, Class>(v_h, std::move(shd_ptr), need_alias);
279+
}
280+
263281
template <typename Class, detail::enable_if_t<is_smart_holder<Holder<Class>>::value, int> = 0>
264282
void construct(value_and_holder &v_h,
265283
std::shared_ptr<Alias<Class>> &&shd_ptr,

include/pybind11/detail/internals.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212
#include <pybind11/conduit/pybind11_platform_abi_id.h>
1313
#include <pybind11/gil_simple.h>
1414
#include <pybind11/pytypes.h>
15+
#include <pybind11/trampoline_self_life_support.h>
1516

1617
#include "common.h"
18+
#include "struct_smart_holder.h"
1719

1820
#include <atomic>
1921
#include <exception>
@@ -35,11 +37,11 @@
3537
/// further ABI-incompatible changes may be made before the ABI is officially
3638
/// changed to the new version.
3739
#ifndef PYBIND11_INTERNALS_VERSION
38-
# define PYBIND11_INTERNALS_VERSION 10
40+
# define PYBIND11_INTERNALS_VERSION 11
3941
#endif
4042

41-
#if PYBIND11_INTERNALS_VERSION < 10
42-
# error "PYBIND11_INTERNALS_VERSION 10 is the minimum for all platforms for pybind11v3."
43+
#if PYBIND11_INTERNALS_VERSION < 11
44+
# error "PYBIND11_INTERNALS_VERSION 11 is the minimum for all platforms for pybind11v3."
4345
#endif
4446

4547
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
@@ -308,6 +310,12 @@ struct type_info {
308310
void *(*operator_new)(size_t);
309311
void (*init_instance)(instance *, const void *);
310312
void (*dealloc)(value_and_holder &v_h);
313+
314+
// Cross-DSO-safe function pointers, to sidestep cross-DSO RTTI issues
315+
// on platforms like macOS (see PR #5728 for details):
316+
memory::get_guarded_delete_fn get_memory_guarded_delete = memory::get_guarded_delete;
317+
get_trampoline_self_life_support_fn get_trampoline_self_life_support = nullptr;
318+
311319
std::vector<PyObject *(*) (PyObject *, PyTypeObject *)> implicit_conversions;
312320
std::vector<std::pair<const std::type_info *, void *(*) (void *)>> implicit_casts;
313321
std::vector<bool (*)(PyObject *, void *&)> *direct_conversions;

0 commit comments

Comments
 (0)