Porting/adapting Dustin's PR #2839 to smart_holder branch #2886
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Hi @virtuald, this PR ports your PR #2839 to the
smart_holder
branch, ready to use if you like to give it a try. The branch is a strict superset of currentmaster
, with pybind11/smart_holder.h as an optional-use add-on.Some remarks:
The test you're adding under Attach python lifetime to shared_ptr passed to C++ #2839 was copied over to here, with a different name:
test_class_sh_trampoline_shared_ptr_cpp_arg
. This way we can merge your PR intomaster
, and then intosmart_holder
without conflicts. After the merge I will try to consolidate the copies, to remove the duplication.The copy-modified test doubles as an example for how to use
smart_holder
(include smart_holder.h, addPYBIND11_SMART_HOLDER_TYPE_CASTERS
macros, changepy::class_
topy::classh
).There is one section in the copy-modified test that expects different behavior compared to your original test, prominently marked with comments. I'm currently unclear if the
has_alias
/is_alias
distinction is actually desirable. I tried a little bit to emulate it, but gave up when I couldn't find a straightforward way to make it work. If you feel strongly the distinction is important, I could try harder to make it work also in thesmart_holder
code.This PR (and the entire
smart_holder
branch) does NOT make any changes that would require aPYBIND11_INTERNALS_VERSION
increment. The trick I'm using is to take a free bit in thesmart_holder
type, to trackpointee_depends_on_holder_owner
. Currently thesmarter_holder
type is not under any version lock policy, because it's still a brand new addition, but after your PR is merged onmaster
, I will look into using yourhas_alias
/is_alias
bits instead. I think it makes more sense to keep those bits separate from the rest of thesmart_holder
logic.Your
shared_ptr_deleter
appears here asshared_ptr_dec_ref_deleter
(I have two other deleters, therefore the more specific name). Note that it works withvoid operator()(void *)
, theT
isn't actually needed. A small simplification / minor optimization, also makes it easier to reuse between our implementations maybe if we want to make things pretty down the road.Note that the
smart_holder
also support passingunique_ptr
back to C++ if safe (disowning the Python object), but ifhas_alias
is true this feature is disabled; a ValueError is raised.For the record, I tried out my idea outlined previously under Attach python lifetime to shared_ptr passed to C++ #2839: populating the
smart_holder
immediately with ashared_ptr
that has your deleter. It was a bad idea: makes a nice reference cycle right there, undetectable by thegc
. Building a newshared_ptr
each time one is needed for passing to C++ is the the only way I could find to achieve the desired behavior.