-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP Add a consume call policy #971
Conversation
612b873
to
799953a
Compare
If I understand correctly, essentially what you're trying to do here is to convert an owned, held reference into an unowned, unheld reference—essentially to turn a regular object into one that would have been created had it been returned with Some comments for fixing this up:
Another idea worth thinking about:
|
Yes, either that, or just completely getting rid of the reference to the object from the Python side, if that's possible at all. However, the solution you described would be just fine too, if not better. Otherwise, thank you for your valuable insight, I will consider your comments thoroughly, and hopefully come up with a more acceptable solution based on them in the future. |
Unfortunately, it isn't: we can't do anything about references to the instance held elsewhere. At best you could replace the pointer with something else, but then the question is what "something else" should be--and since it has to be some sort of object that you're going to have to duplicate, you might as well just consume the duplicate. (I suppose you could add some sort of error detection for trying to use an instance that is already cleared, but that's going a bit far into esoteric territory). |
I meant removing just that single reference which was passed to the function. Something like an implicit del statement with that name. If other references are held to it... Well, I don't think we can/should do much about them. But never mind, deleting is really not that important. And if I make the reference into a non-holding weak one, is that going to apply to all Python references? Is there only a single holder for a given instance that is used by all Python references, or all references have their own holders? |
I think the key thing to realize is that every variable in Python is essentially a shared reference; the instance that gets passed into the function is the same instance held by other copies of that variable. So yes, any changes to one variable are going to affect every other reference to that variable. The holder itself is unique, by default, but the holder is inside the object; each python variable is simply a reference to that one object. |
Awesome, thanks! I knew how Python references work, just wasn't sure if there isn't any black magic to somehow keep track of all Python references to an object, and assign a different holder to all of them. However, in hindsight, I'm not sure why this even came up in my mind, it would be kind of silly and pointless. |
799953a
to
689cb12
Compare
Superseded by #1226. See details for closing there. |
I tried to interface with a C++ library that has a couple of functions which take ownership of some of their pointer parameters.
I could not find a way to call them from Python using pybind11, because they kept being either double-freed or leaked.
An included test demonstrates this use case with a minimal, and not very elegant example.
This is my attempt to add a call policy named consume. It means that the ownership of any parameters marked by it is taken by the called C++ function, and must not be accessed or deleted by Python code or pybind11 after the call.
It is incomplete, because I could not figure out how to make it work in the general case, with custom holder types. I have marked the code with ??? where I tried to do something that did not work out.
Any help is much appreciated.