Skip to content

pybind11 fork: Ensure failed overload with unique_ptr returns ownership #8160

@EricCousineau-TRI

Description

@EricCousineau-TRI

@apojomovsky ran into a situation where a set of ovlerloads look like something to the effect of:

py::class_<Container>(m, "Container")
  .def(py::init<unique_ptr<A>, FirstT>())
  .def(py::init<unique_ptr<A>, SecondT>());

When Python calls something like:

c = Container(A(), SecondT())

this will most likely failure with the following error:

RuntimeError: C++ object must be owned by pybind11 when attempting to release to C++

This most likely happens since pybind11::detail::argument_loader does not have a "transaction" mechanism of sort; the cast of unique_ptr<A> succeeds when it tries to match the first overload, but when it is unable to load the second argument, it will just exit out, and not try to reverse the ownership transfer:
https://github.com/RobotLocomotion/pybind11/blob/060f8eb/include/pybind11/cast.h#L2138

The solution is to introduce some sort of "transaction" mechanism.

From what it looks like, I detect ownership transfer from the move_only_holder_caster; if the caster is destructed without having transferred the object, then it can reverse the ownership transfer (simply calling cast to release ownership back to Python).

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions