From 6f676d39c26810bb156cc9768ea01dde1c4bc435 Mon Sep 17 00:00:00 2001 From: Jeremy Nimmer Date: Wed, 15 Jan 2025 07:33:28 -0800 Subject: [PATCH] [py lcm] Adjust CreateDefaultValue to avoid unique_ptr This reduces our reliance RLG/pybind11 custom unique_ptr semantics. --- bindings/pydrake/systems/lcm_py.cc | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/bindings/pydrake/systems/lcm_py.cc b/bindings/pydrake/systems/lcm_py.cc index 8cfb9d1b2994..d5895fbda3a5 100644 --- a/bindings/pydrake/systems/lcm_py.cc +++ b/bindings/pydrake/systems/lcm_py.cc @@ -40,9 +40,18 @@ class PySerializerInterface : public py::wrapper { // `PySerializerInterface`). C++ implementations will use the bindings on the // interface below. - std::unique_ptr CreateDefaultValue() const override { - PYBIND11_OVERLOAD_PURE(std::unique_ptr, SerializerInterface, - CreateDefaultValue); + std::unique_ptr CreateDefaultValue() const final { + // Our required unique_ptr return type cannot be directly fulfilled by a + // Python override, so we only ask the Python override for a py::object and + // then just Clone it to obtain the necessary C++ signature. Because the + // PYBIND11_OVERLOAD_PURE macro embeds a `return ...;` statement, we must + // wrap it in lambda so that we can post-process the return value. + py::object default_value = [this]() -> py::object { + PYBIND11_OVERLOAD_PURE( + py::object, SerializerInterface, CreateDefaultValue); + }(); + DRAKE_THROW_UNLESS(!default_value.is_none()); + return default_value.template cast()->Clone(); } void Deserialize(const void* message_bytes, int message_length,