Uh oh!
There was an error while loading. Please reload this page.
Nicer API to pass py::capsule destructor - #752
Conversation
virtuald
commented
Mar 20, 2017
I'm already using it in a module deployed to pypi.. any chance you can add a macro to detect the API change? :( |
wjakob
commented
Mar 20, 2017
If it becomes part of 2.1 or 2.2, you can of course #ifdef based on |
dean0x7d
left a comment
There was a problem hiding this comment.
Nice, this definitely also removes the ambiguity of whether to borrow or steal that PyObject*.
| pybind11_fail("Could not allocate capsule object!"); | ||
| } | ||
| explicit capsule(const void *value, void (*destructor)(void *)) { |
| PYBIND11_OBJECT_DEFAULT(capsule, object, PyCapsule_CheckExact) | ||
| PYBIND11_DEPRECATED("Use reinterpret_borrow<capsule>() or reinterpret_steal<capsule>()") | ||
| capsule(PyObject *ptr, bool is_borrowed) : object(is_borrowed ? object(ptr, borrowed) : object(ptr, stolen)) { } | ||
| explicit capsule(const void *value, void (*destruct)(PyObject *) = nullptr) |
There was a problem hiding this comment.
Maybe just deprecate this constructor for backward compatibility? (Just without the = nullptr default and explicit).
| pybind11_fail("Could not allocate capsule object!"); | ||
| } | ||
| explicit capsule(const void *value, void (*destructor)(void *)) { |
There was a problem hiding this comment.
I was thinking it would be nice to make this take a function with a (deduced) T * argument, with a reinterpret cast of the capsule pointer to the deduced type when invoking the destructor. Unfortunately I think that would require some special handling to accept a lambda, so might not be worthwhile.
There was a problem hiding this comment.
That's what I had implemented at first (with an extra closure object stored in the capsule context), but it struck me as a bit overkill.
There was a problem hiding this comment.
(In any case, that sort of thing can still be added later on if there a good case for this functionality can be made. This PR is about preventing fallout from a problematic API that is about to be documented.)
wjakob
commented
Mar 20, 2017
Thanks @dean0x7d, I added a deprecated constructor now. I'll merge this into 2.1 unless there are objections. |
jagerman
commented
Mar 20, 2017
No objections. |
I'm not sure how common the use case of #733 is -- would it warrant adding a dedicated constructor? E.g. |
jagerman
commented
Mar 20, 2017
I think it would be nice to have. I don't understand why Python imposes |
virtuald
commented
Mar 20, 2017
Well, the only reason why #733 uses a capsule is because module destructors aren't exposed. If they were, then it would just be added to wherever the module docs are and wouldn't need to worry about capsules. Of course, only Python 3 supports module destructors IIRC, so you'd need this hack anyways -- but maybe it could be done internally? |
jagerman
commented
Mar 21, 2017
Module destructors, using this as a workaround for Python 2, seems like a useful addition, but can be added later (i.e. for 2.2). |
jagerman
commented
Mar 22, 2017
This is the last 2.1 PR; I think it's good as is, but the dummy-pointer version might also be useful. (Though I think it can wait as well, if you prefer to merge without it). |
wjakob
commented
Mar 22, 2017
I had the same thought and just added it. |
wjakob
commented
Mar 22, 2017
Added docs & the destructor-only capsules. |
That's a pretty weird PyPy failure -- it looks like the pytest capture object is not working. |
jagerman
commented
Mar 22, 2017
Rebase against current master: I just pushed a change to use pypy 5.7 instead of the 5.8 nightly in the travis-ci test, which fixes the PyPy build. |
wjakob
commented
Mar 22, 2017
thanks -- done. |
jagerman
commented
Mar 22, 2017
I just turned on this cool new travis-ci setting for pybind11 PR builds: https://blog.travis-ci.com/2017-03-22-introducing-auto-cancellation |
wjakob
commented
Mar 22, 2017
Cool -- that's a useful feature indeed! |
jagerman
commented
Mar 22, 2017
Hmm, that didn't fix the PyPy test failure. I wonder if you could work around it by not using a capture, perhaps by setting/checking a static variable? |
dean0x7d
commented
Mar 22, 2017
Doesn't PyPy need a couple of GC calls after a |
wjakob
commented
Mar 22, 2017
that's right -- I forgot about that. |
| a = m.return_capsule_with_destructor_2() | ||
| del a | ||
| pytest.gc_collect() | ||
| print(capture) |
wjakob
commented
Mar 22, 2017
that cancel feature is already starting to pay off :) |
wjakob
commented
Mar 22, 2017
Ok, that did it! |
Use `PyCapsule_Destructor` (part of the stable Python ABI) instead of spelling out the C `typedef`. The deprecation message is misleading. Replace with a message pointing to another existing ctor. Background: According to @wjacob the original motivation for deprecating the ctor (in PR pybind#752) was to hide Python C API details, but PR pybind#902 brought those back with a new ctor, it cannot be avoided. Having a `PyCapsule_Destructor` or a `void (*destructor)(void *)` are two separate and valid use cases.
Use `PyCapsule_Destructor` (part of the stable Python ABI) instead of spelling out the C `typedef`. The deprecation message is misleading. Replace with a message pointing to another existing ctor. Background: According to @wjakob the original motivation for deprecating the ctor (in PR pybind#752) was to hide Python C API details, but PR pybind#902 brought those back with a new ctor, it cannot be avoided. Having a `PyCapsule_Destructor` or a `void (*destructor)(void *)` are two separate and valid use cases.
Use `PyCapsule_Destructor` (part of the stable Python ABI) instead of spelling out the C `typedef`. The deprecation message is misleading. Replace with a message pointing to another existing ctor. Background: According to @wjakob the original motivation for deprecating the ctor (in PR #752) was to hide Python C API details, but PR #902 brought those back with a new ctor, it cannot be avoided. Having a `PyCapsule_Destructor` or a `void (*destructor)(void *)` are two separate and valid use cases.
The current way of specifying a destructor for
py::capsuleinstances strikes me as quite inelegant (the Python C API leaks through, requiring the user to deal withPyCapsule_GetPointer). This PR changes the convention.