mirror of
https://github.com/pybind/pybind11.git
synced 2026-03-14 20:27:47 +00:00
* Fix Python 3.8 type hints and add module prefix These type hints are invalid in Python 3.8. Add `typing.` prefix to remove ambiguity. * style: pre-commit fixes * Add module prefix to Union * Rename macros * Improve comment * Comment out 3.8 type hint macros Fixing this issue in Python 3.8 will require updating lots of tests. This can be added in a further pull request. * Add Iterable module prefix * Add module prefix to Iterator * Add module prefix to Callable * Re-add accidentally deleted brackets * Add module prefix to Optional * Add module prefix to Final * Add module prefix to ClassVar * Add module prefix to TypeGuard * Add module prefix to TypeIs * Add module prefix to NoReturn * Add module prefix to Never * Add module prefix to Literal * Add module prefix to Callable * Add module prefix to Sequence * Add module prefix to Iterator * style: pre-commit fixes * Remove type hint macros * style: pre-commit fixes --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
70 lines
2.6 KiB
C++
70 lines
2.6 KiB
C++
// #########################################################################
|
|
// PLEASE UPDATE docs/advanced/cast/custom.rst IF ANY CHANGES ARE MADE HERE.
|
|
// #########################################################################
|
|
|
|
#include "pybind11_tests.h"
|
|
|
|
namespace user_space {
|
|
|
|
struct Point2D {
|
|
double x;
|
|
double y;
|
|
};
|
|
|
|
Point2D negate(const Point2D &point) { return Point2D{-point.x, -point.y}; }
|
|
|
|
} // namespace user_space
|
|
|
|
namespace pybind11 {
|
|
namespace detail {
|
|
|
|
template <>
|
|
struct type_caster<user_space::Point2D> {
|
|
// This macro inserts a lot of boilerplate code and sets the type hint.
|
|
// `io_name` is used to specify different type hints for arguments and return values.
|
|
// The signature of our negate function would then look like:
|
|
// `negate(collections.abc.Sequence[float]) -> tuple[float, float]`
|
|
PYBIND11_TYPE_CASTER(user_space::Point2D,
|
|
io_name("collections.abc.Sequence[float]", "tuple[float, float]"));
|
|
|
|
// C++ -> Python: convert `Point2D` to `tuple[float, float]`. The second and third arguments
|
|
// are used to indicate the return value policy and parent object (for
|
|
// return_value_policy::reference_internal) and are often ignored by custom casters.
|
|
// The return value should reflect the type hint specified by the second argument of `io_name`.
|
|
static handle
|
|
cast(const user_space::Point2D &number, return_value_policy /*policy*/, handle /*parent*/) {
|
|
return py::make_tuple(number.x, number.y).release();
|
|
}
|
|
|
|
// Python -> C++: convert a `PyObject` into a `Point2D` and return false upon failure. The
|
|
// second argument indicates whether implicit conversions should be allowed.
|
|
// The accepted types should reflect the type hint specified by the first argument of
|
|
// `io_name`.
|
|
bool load(handle src, bool /*convert*/) {
|
|
// Check if handle is a Sequence
|
|
if (!py::isinstance<py::sequence>(src)) {
|
|
return false;
|
|
}
|
|
auto seq = py::reinterpret_borrow<py::sequence>(src);
|
|
// Check if exactly two values are in the Sequence
|
|
if (seq.size() != 2) {
|
|
return false;
|
|
}
|
|
// Check if each element is either a float or an int
|
|
for (auto item : seq) {
|
|
if (!py::isinstance<py::float_>(item) && !py::isinstance<py::int_>(item)) {
|
|
return false;
|
|
}
|
|
}
|
|
value.x = seq[0].cast<double>();
|
|
value.y = seq[1].cast<double>();
|
|
return true;
|
|
}
|
|
};
|
|
|
|
} // namespace detail
|
|
} // namespace pybind11
|
|
|
|
// Bind the negate function
|
|
TEST_SUBMODULE(docs_advanced_cast_custom, m) { m.def("negate", user_space::negate); }
|