Skip to content

Questions about __pyx_capi__ use/stability. #3077

Open

Description

@stuartarchibald

A common use case when extending Numba is to use an existing Cython extension module to provide access points to the compiled functions contained within. For Numba to do this the __pyx_capi__ attribute must be queried. Examples and discussion here: numba/numba#3086 and API guide here http://numba.pydata.org/numba-doc/latest/extending/high-level.html#importing-cython-functions.

Recently work has started on numba-scipy to add SciPy support to Numba, this PR numba/numba-scipy#12 notes that __pyx_capi__ is a Cython internal.

The crux of all this is I think a few questions:

  1. Is __pyx_capi__ sufficiently ingrained in Cython that it can be relied upon being present indefinitely.
  2. Is __pyx_capi__ truly internal? Or are there cases in practice where users are parsing/using it (pythran does already?!)?
  3. Is the form of __pyx_capi__ stable/consistent.

Thanks in advance for your help!

Activity

  1. leofang commented on Nov 5, 2024

    @leofang

    +1 for all the questions that @stuartarchibald asked.

    We hit this issue recently because we wanted to have a trampoline module (with an old name/path) to "re-export" all Cython symbols from another (new) module to keep a smooth transition to the latter, and it seems a plain cimport in the trampoline is not enough, and we need to hack at the __pyx_capi__ level.

  2. da-woods commented on Nov 6, 2024

    @da-woods
    Collaborator

    I'm reluctant to say it's completely fine to use it. However, we are aware that people are using it. And we've also found in the past that it's really difficult to change it because it's really supposed to match between Cython versions.

    So it's likely to be stable, but I wouldn't absolutely promise it.

  3. matusvalo commented on Nov 6, 2024

    @matusvalo
    Contributor

    So it's likely to be stable, but I wouldn't absolutely promise it.

    I think that it is already used so we should not change it without proper deprecation & replacement in any case. Also it seems to be important for the clients. So I think it is better to document it. I created an issue for that - #6484.

    Fixing #6484 should also close this issue because all questions should be clear from the docs.

  4. matusvalo commented on Nov 6, 2024

    @matusvalo
    Contributor

    I am thinking aloud. As an alternative to providing __pyx_capi__ as part of API does it make sense to provide function (eg. cython.cimport()) which dynamicaly cimports functions similar to numbas?

    https://github.com/numba/numba/blob/0f363d1b2dd19f2aa1a8cec5f0a99c3dd95512f8/numba/_helperlib.c#L561

  5. da-woods commented on Nov 7, 2024

    @da-woods
    Collaborator

    As an alternative to providing __pyx_capi__ as part of API does it make sense to provide function (eg. cython.cimport()) which dynamicaly cimports functions similar to numbas?

    I think it'd necessarily have to be visible through a Python interface (otherwise people wouldn't be able to access it easily).

    That limits how we chose to return C function pointers back. It'd either be a PyCapsule (in which case it's very similar to __pyx_capi__), or a Python int, or maybe a ctypes function pointer?

  6. stuartarchibald commented on Nov 7, 2024

    @stuartarchibald
    Author

    Thanks for taking a look at this issue, I'm glad that __pyx_capi__ is going to be considered stable and documented through #6484. Numba has been relying on it for quite a while!

    To the discussion... from Numba's point of view, the JIT compiler part just needs the address of a symbol and a prototype for calling it. The code linked above in _helperlib.c is simply there to hide the internal mechanics from the user and expose the address from the retrieved PyCapsule. Making an interface Python accessible would be helpful, Numba's PIXIE project is doing something similar, it exposes everything about the compiled C-extension through a module level dictionary in the extension itself. As to returning function pointers, I don't know how easy it is to handle PyCapsules from Python itself, the situation may have changed since I opened the issue/did the original work, but at the time I seem to recall there was very little available to handle them.

  7. scoder commented on Nov 8, 2024

    @scoder
    Contributor
  8. da-woods commented on Nov 8, 2024

    @da-woods
    Collaborator

    I'm reluctant to make guarantees about the exact signature/ID strings that we use for the capsules, for example. To a certain extent, they expose internals that I would like to be able to change rather freely. There may not be a high chance of them changing any time soon, but considering that a guarantee seems far fetched.

    We've failed to change them before because changing them would mean that you couldn't cimport a module compiled with a different Cython version.

    There was an issue (that I can't find right now) where Pandas/scipy/similar wanted to change their function arguments from int to const int (which is considered identical from a C point-of-view) but they couldn't do it because it changed the __pyx_capi__ signature, which broke cimports for anyone using the public pxd file.

    Which to me suggests we're pretty limited in how we can change this ourselves.


    So while I don't think this mechanism is likely to change soon, I'm not sure we should formally document it. I think we should just tolerate and be a bit considerate of people using it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions