Replies: 6 comments 2 replies
-
Isn't that precisely what Besides this, a major change would be that the approach of creating multiple shared pointers with a custom deleter that holds a reference would no longer work. There would need to be a more advanced deleter replacement that handles everything with a single instance and while being compatible with the case that an object was not constructed by nanobind. It might be possible but surely sounds complicated. One last constraint: nanobind is designed to pull in a truly minimal number of C++ headers. Generally my idea with this library was that pybind11 is great for handling all kinds of use cases, but it ends up being pretty complex as a consequence. Nanobind is opinionated and ignores use cases to be simpler+faster, which will usually require adaptations in the c++ code to be bound. If you can find a way to generalize the current approach while preserving its simplicity, I am definitely open to it. FYI: I am on vacation for a couple of days. I will review your datetime PR when I am back. |
Beta Was this translation helpful? Give feedback.
-
Calling
Obviously anything in the STL will be used in different ways by different people, but the only way I've personally used
I actually think it would work fine? There is no need for the shared_ptr that It would also be easy to change the Another way to think about it:
This is why I proposed adding the requirement that
I respect that approach, and I'm only interested in supporting Enjoy your vacation -- thanks for being open to discussing this! |
Beta Was this translation helpful? Give feedback.
-
Long comments ... sorry I cannot read through all of it. @oremanj did you already see the PR description here? Small rant: I think of But the pybind11 smart_holder branch supports it to the fullest extend possible, and the implementation has been completely stable since June/July 2021. |
Beta Was this translation helpful? Give feedback.
-
@rwgk thank you for the link! I was in fact not familiar with the pybind11
Good point. What I mean is a little more subtle: assuming
But both of these will work if you return or accept |
Beta Was this translation helpful? Give feedback.
-
enable_shared_from_this is now supported! |
Beta Was this translation helpful? Give feedback.
-
To make it easier to backtrack in the future:
that was #212 |
Beta Was this translation helpful? Give feedback.
-
I've read the docs and thought about it fairly extensively. I'm failing to come up with a scenario where nanobind's guard against types that use
std::enable_shared_from_this
would actually prevent a dangling pointer or other form of UB.The docs say:
I think of
enable_shared_from_this
as a meeting-place: if someone has created a shared_ptr for an object (whose lifetime hasn't ended yet), it provides a way for others to locate it and share ownership with the first person. If the initial shared_ptr creation was valid (made by someone with ownership of a resource -- even if that resource is "one refcount on the owning PyObject*" -- and made with a deleter that properly disposes of the resource), I don't see how letting more owners join in creates a problem. nanobind already has to assume when it passes a shared_ptr into C++ that it might be used to create multiple C++-side shared owners.About the only way I can imagine
enable_shared_from_this
causing problems is if some C++ code gets aT*
, tries to extract itsshared_ptr<T>
, finds that there isn't one, and then decides to create one that assumes theT*
is heap-allocated and doesn't have any other owners. That seems like quite a large leap of faith, and I'd call it a bug in the code that's assuming ownership in that way -- a raw pointer doesn't offer that sort of license. If you need ashared_ptr
and you don't have one, you can't just magic one into existence. Is there really enough code in the wild that does this that it's worth banning the whole pattern? Or is there some other situation that I'm missing here?My current belief is that if I were to eliminate the
shared_from_this
assertion, eliminate thevoid*
casting in the shared_ptr type caster that's commented as being designed to defeatenable_shared_from_this
, and make sureenable_shared_from_this
types were only passed across the C++/Python boundary when wrapped inshared_ptr
, then everything would work fine as long as I don't have any code that does the sketchy ownership assumptions described in the previous paragraph. I understand that this is a higher degree of care than you might be willing to assume of the average nanobind user, but it seems like a far cry from the "enable_shared_from_this is fundamentally impossible to support" message I got from the documentation, so I wanted to double-check my understanding.Beta Was this translation helpful? Give feedback.
All reactions