py::cast on non-polymorphic base class pointer does not find existing derived instance
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 18k
- Forks
- 2.3k
- Avg merge
- 5d 17h
- Merged PRs (30d)
- 10
Description
Issue description
I'm not sure if this is a bug or just a limitation of what pybind11 can do, but it could merit at least a mention in the docs or the FAQ.
When using py::cast to convert a C++ pointer to a py::object, if the pointer has a base class type but actually points to a derived object that was created from Python, it fails to recognise that this is an existing instance and instead creates a second Python wrapper.
If the base class is made polymorphic, then everything works. However, I have a base class I don't want to be polymorphic for performance reasons.
The use case is that I need to get a Python handle to this inside a method that is being exposed to Python, for lifetime management purposes (it's a case that won't fit into the standard call policies).
Tested on v2.2.0-38-g6a81dbb.
Reproducible example code
#include <pybind11/pybind11.h>
namespace py = pybind11;
class Base {};
class A : public Base {};
PYBIND11_MODULE(variant, m) {
py::class_<Base>(m, "Base")
.def("show", [] (const Base &base)
{
py::print("I am", py::cast(&base));
});
py::class_<A, Base>(m, "A");
m.def("make_a", []() -> py::object
{
py::object obj = py::cast(A());
py::print("Created", obj);
return obj;
});
}
from variant import make_a
a = make_a()
a.show()
Output:
Created <variant.A object at 0x7fc7288b3ce0>
I am <variant.Base object at 0x7fc7288b3d18>
Expected output:
Created <variant.A object at 0x7fc7288b3ce0>
I am <variant.A object at 0x7fc7288b3ce0>
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by running the supplied C++ binding and Python example to reproduce the duplicate wrapper for a non-polymorphic base pointer. Trace the py::cast path involved in converting the base pointer and compare it with the polymorphic case. Done means the existing A instance is returned, or the limitation is documented in the docs or FAQ.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, python
- Domain
- api, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100