I have a setup in which a resource R
may be passed through various filters F
also deriving from R
. It makes no sense to share ownership of an R
because the resource is consumed upon retrieval. Some I decided to use unique_ptr
as follows:
struct R{
virtual int yield() = 0;
};
struct F{
F(std::unique_ptr<R> r): _r(std::move(r)) {}
int yield(){return _r->yield() + 1;}
std::unique_ptr<R> _r;
};
except that of course the classes are more interesting. Now I am trying to bind that with pybind11. Pybind seems not to like unique_ptr
, as stated in the docs. How can I circumvent this? I see to possibilities:
std::unique_ptr
by something pybind11 understands. That would mean that on both the C++ and the Python side, an R
can be fed into F
although the R
has already been consumed by some other F
.
std::unqique_ptr
, take R*&
. Then transfer of ownership can be reflected with setting the parameter to zero. Seems not very C++y, though.F
that needs no unique_ptr
. This would have the same problem, but only on the Python side. I could implement something taking care of this, probably. Plus, I wouldn't need to change the interface of existing code. Downside, I need to replicate all methods I need.Both solutions don't seem too appealing. What would be an alternative?
One of the issues of language interop is that you have to obey the data model of both languages. Python doesn't have the conception of unique ownership of a resource, which is why pybind doesn't let you have std::unique_ptr
as parameters exposed to Python.
I think the easiest way would be to use std::shared_ptr
, but comment that this is only for interop with the Python binding. You can still have F::F(std::unique_ptr<R> r)
for the C++ side, because there is a converting constructor std::shared_ptr<R>::shared_ptr(std::unique_ptr<R>)
.