welder
0.1.0
Bindings for annotated C++ types, from C++26 reflection
Toggle main menu visibility
Loading...
Searching...
No Matches
trampoline.hpp
Go to the documentation of this file.
1
#pragma once
2
#include <cstddef>
3
#include <meta>
4
#include <type_traits>
5
#include <utility>
6
7
#include <
welder/rods/python/trampoline.hpp
>
// virtual_slot_count, trampoline_for, …
8
9
#include <pybind11/pybind11.h>
10
28
29
namespace
welder::inline v0::rods::pybind11 {
30
31
// The unqualified name `pybind11` resolves to *this* namespace inside it; alias the
32
// real library the way pybind11's own docs do (see rod.hpp).
33
namespace
py
= ::pybind11;
34
63
template
<
auto
Fn,
typename
Self,
typename
BaseCall,
typename
... Args>
64
decltype
(
auto
)
override_dispatch
(
const
Self& self, BaseCall&& base_call,
65
Args&&... args) {
66
using
ret_type = [:std::meta::return_type_of(Fn):];
67
static_assert
(
68
!std::is_reference_v<ret_type>,
69
"welder: cannot trampoline a virtual method that returns a reference "
70
"(pybind11 cannot keep the referent alive across the C++/Python boundary); "
71
"return by value, or mark the type [[=welder::rods::python::bind_flat]]."
);
72
73
constexpr
const
char
* name{
74
std::define_static_string(std::meta::identifier_of(Fn))};
75
76
py::gil_scoped_acquire gil;
77
py::function
override
{py::get_override(&self, name)};
78
if
(
override
)
79
return
py::detail::cast_safe<ret_type>(
80
override
(std::forward<Args>(args)...));
81
82
if
constexpr
(std::meta::is_pure_virtual(Fn))
83
// No base to fall back to and no Python override: pybind11's own diagnostic.
84
py::pybind11_fail(
85
"welder: tried to call a pure virtual method with no Python override"
);
86
else
87
return
std::forward<BaseCall>(base_call)(std::forward<Args>(args)...);
88
}
89
90
}
// namespace welder::rods::pybind11
91
98
#define WELDER_PY_TRAMPOLINE(BASE) \
99
using welder_py_base = BASE; \
100
using welder_py_base::welder_py_base
101
114
#define WELDER_PY_OVERRIDE_AS(SLOT, FUNC, ...) \
115
return ::welder::rods::pybind11::override_dispatch<(SLOT)>( \
116
static_cast<const welder_py_base&>(*this), \
117
[&](auto&&... _welder_a) -> decltype(auto) { \
118
return welder_py_base::FUNC( \
119
static_cast<decltype(_welder_a)&&>(_welder_a)...); \
120
} __VA_OPT__(, ) __VA_ARGS__)
121
130
#define WELDER_PY_OVERRIDE(FUNC, ...) \
131
WELDER_PY_OVERRIDE_AS(^^welder_py_base::FUNC, FUNC __VA_OPT__(, ) __VA_ARGS__)
welder::rods::pybind11
Definition
rod.hpp:45
welder::rods::pybind11::override_dispatch
decltype(auto) override_dispatch(const Self &self, BaseCall &&base_call, Args &&... args)
Dispatch a captured virtual call to its Python override, else to the C++ base.
Definition
trampoline.hpp:64
welder::lang::py
@ py
Python (via the pybind11 and nanobind backends).
Definition
lang.hpp:43
trampoline.hpp
Virtual-function overriding support shared by welder's Python backends.
src
welder
rods
python
pybind11
trampoline.hpp
Generated by
1.17.0