-
-
Notifications
You must be signed in to change notification settings - Fork 52
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
Introduce capsule API #308
Conversation
It seems this is required for the graal-team/hpy branch of numpy. Were there any more thoughts about how to do global state for the desctuctor? |
Not connected to this PR, but I also see h_ComplexType in the numpy branch. Is there a PR or issue to add that to the HPyContext? |
... and HPyTupleBuilder_IsNull as well... |
Yes.
Not sure if I understand your question. Anyway, I didn't think about other solutions since then. Ideas are welcome. |
Adding this to the 0.9 milestone since it is needed for the NumPy port. |
Needs a rebase |
sure, I'll do that |
@fangerer waiting for a rebase to merge this |
Yes, still on my list. I'm sorry for the delay. I got sick (I'm still on leave) but will return tomorrow. |
C++ is not happy with the capsule code:
|
LGTM. I will merge once CI passes, if no-one objects. |
🥳 thank you, Matti |
(Sorry to chime in just few hours after the PR has been merged 🤦♂️ )
I might be missing something here, but I think that we could use the same technique that we used for hpy/hpy/devel/include/hpy/hpydef.h Lines 21 to 27 in 414be8b
i.e., instead of passing a pointer to a function, we could pass a pointer to a struct which contains two function pointers (one to the user-provided code, and one to the autogenerated cpy trampoline). Something like this: typedef void (*HPyFunc_capsule_dtor)(const char *name, void *pointer, void *context);
typedef struct {
cpy_PyCapsule_Destructor cpy_trampoline;
HPyFunc_capsule_dtor impl;
} HPyCapsule_Destructor; Then the user will have to use a macro to generate the struct: /* this automatically generate the trampoline and fills a statically allocated
struct called 'my_dtor' */
HPyCapsule_DESTRUCTOR(my_dtor, my_dtor_impl);
void my_dtor_impl(const char *name, void *pointer, void *context) {
...
}
void init() {
...
HPyCapsule c = HPyCapsule_New(ctx, "foo.bar", myptr, &my_dtor);
} |
It's not too late, this could be an add-on PR to enhance the current code. Would you want to make a PR? |
No, it's not too late. That's a good suggestion. Sorry, the PR is so old that I didn't spent too much thoughts on it recently. |
ok, I've opened an issue for it to ensure that we don't forget |
This introduces an
HPyCapsule
API similar toPyCapsule
.While the capsule API isn't use a lot in the top4000 packages, it's needed for our NumPy migration efforts.
Main goals to achieve were:
HPyCapsule
should be interchangeable withPyCapsule
. So, one can create anHPyCapsule
, store into some attribute and a completely unrelated C API extension could use it via thePyCapsule
API (and vice versa).HPyCapsule_*
functions toPyCapsule_*
functions in CPython ABI mode.The implementation for CPython is mostly straight forward except of the destructor. This was the main problem is should probably be the main discussion point here.
The capsule destructor function has signature
void (*PyCapsule_Destructor)(PyObject *)
and is also exposed to the user withPyCapsule_Get/SetDestrutor
.I've introduced signature
void (*HPyCapsule_Destructor)(const char *name, void *pointer, void *context)
that will receive the contents of the capsule but not the object itself (and no HPy context, ofc).However, we now cannot directly map the HPy destructor to a CPython one, we need a trampoline. This one needs to know the function pointer of the
HPyCapsule_Destructor
butPyCapsule
does not give you the possibility to store this pointer somewhere. I've considered:name
field and storing the pointer before the name but the name is optional.The only reliable solution I could think of was to have a global registry somewhere. I decided to put it into the interpreter state's dict (Python >= 3.8) or into the sys module (using
PySys_Get/SetObject
for Python < 3.8).