Skip to content

[BUG]: py::cast() from std::shared_ptr throws with custom holder #6064

@pobrn

Description

@pobrn

Required prerequisites

What version (or hash if on master) of pybind11 are you using?

3.0.4

Problem description

The libcamera project provides python bindings via pybind11. One particular type has a private destructor and is managed via std::shared_ptr. It has a custom holder to work around the need for a public destructor.

This has worked so far, but now it does work not with pybind11 3.0.4. Specifically, calling py::cast() on an std::shared_ptr of that type in question throws:

>>> import libcamera
>>> cm = libcamera.CameraManager.singleton()
>>> cm.cameras
RuntimeError: Unable to convert std::shared_ptr<T> to Python when the bound type does not use std::shared_ptr or py::smart_holder as its holder type

As far as I can see this has been added by #6008. So I'm wondering, is this exception diagnosing a real issue, or the above PR missed some cases?

It seems to work with py::smart_holder, but this code predates that, so it wasn't used.

holder type
template<typename T>
class PyCameraSmartPtr
{
public:
	using element_type = T;

	PyCameraSmartPtr()
	{
	}

	explicit PyCameraSmartPtr(T *)
	{
		throw std::runtime_error("invalid SmartPtr constructor call");
	}

	explicit PyCameraSmartPtr(std::shared_ptr<T> p)
		: ptr_(std::move(p))
	{
	}

	T *get() const { return ptr_.get(); }

	operator std::shared_ptr<T>() const { return ptr_; }

private:
	std::shared_ptr<T> ptr_;
};

PYBIND11_DECLARE_HOLDER_TYPE(T, PyCameraSmartPtr<T>)

// ...

auto pyCamera = py::class_<Camera, PyCameraSmartPtr<Camera>>(m, "Camera");

Reproducible example code


Is this a regression? Put the last known working version here if it is.

3.0.2 (?)

Metadata

Metadata

Assignees

No one assigned

    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