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 <nanobind/nanobind.h>
10
#include <nanobind/trampoline.h>
11
27
28
namespace
welder::inline v0::rods::nanobind {
29
30
// The unqualified name `nanobind` resolves to *this* namespace inside it; alias the
31
// real library the way nanobind's own docs do (see rod.hpp).
32
namespace
nb = ::nanobind;
33
54
template
<
auto
Fn, std::size_t N,
typename
BaseCall,
typename
... Args>
55
decltype
(
auto
)
override_dispatch
(
const
nb::detail::trampoline<N>& tr,
56
BaseCall&& base_call, Args&&... args) {
57
using
ret_type = [:std::meta::return_type_of(Fn):];
58
static_assert
(
59
!std::is_reference_v<ret_type>,
60
"welder: cannot trampoline a virtual method that returns a reference "
61
"(nanobind cannot keep the referent alive across the C++/Python boundary); "
62
"return by value, or mark the type [[=welder::rods::python::bind_flat]]."
);
63
64
constexpr
const
char
* name{
65
std::define_static_string(std::meta::identifier_of(Fn))};
66
67
if
constexpr
(std::meta::is_pure_virtual(Fn)) {
68
// Pure: there is no base to fall back to. nanobind's trampoline machinery
69
// raises a descriptive error if Python supplied no override.
70
nb::detail::ticket t(tr, name,
/*pure=*/
true
);
71
return
nb::cast<ret_type>(tr.base().attr(t.key)(std::forward<Args>(args)...));
72
}
else
{
73
nb::detail::ticket t(tr, name,
/*pure=*/
false
);
74
if
(t.key.is_valid())
75
return
nb::cast<ret_type>(
76
tr.base().attr(t.key)(std::forward<Args>(args)...));
77
return
std::forward<BaseCall>(base_call)(std::forward<Args>(args)...);
78
}
79
}
80
81
}
// namespace welder::rods::nanobind
82
90
#define WELDER_PY_TRAMPOLINE(BASE) \
91
using welder_py_base = BASE; \
92
using welder_py_base::welder_py_base; \
93
::nanobind::detail::trampoline< \
94
::welder::rods::python::virtual_slot_count(^^BASE)> \
95
welder_nb_trampoline{this}
96
109
#define WELDER_PY_OVERRIDE_AS(SLOT, FUNC, ...) \
110
return ::welder::rods::nanobind::override_dispatch<(SLOT)>( \
111
this->welder_nb_trampoline, \
112
[&](auto&&... _welder_a) -> decltype(auto) { \
113
return welder_py_base::FUNC( \
114
static_cast<decltype(_welder_a)&&>(_welder_a)...); \
115
} __VA_OPT__(, ) __VA_ARGS__)
116
125
#define WELDER_PY_OVERRIDE(FUNC, ...) \
126
WELDER_PY_OVERRIDE_AS(^^welder_py_base::FUNC, FUNC __VA_OPT__(, ) __VA_ARGS__)
welder::rods::nanobind
Definition
rod.hpp:51
welder::rods::nanobind::override_dispatch
decltype(auto) override_dispatch(const nb::detail::trampoline< N > &tr, BaseCall &&base_call, Args &&... args)
Dispatch a captured virtual call to its Python override, else to the C++ base.
Definition
trampoline.hpp:55
trampoline.hpp
Virtual-function overriding support shared by welder's Python backends.
src
welder
rods
python
nanobind
trampoline.hpp
Generated by
1.17.0