Skip to content
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

Enhancing jlwrap #733

Closed
wants to merge 6 commits into from
Closed

Enhancing jlwrap #733

wants to merge 6 commits into from

Conversation

cjdoris
Copy link

@cjdoris cjdoris commented Dec 20, 2019

Re #617, this extends the functionality of jlwrap. I'll explain this a bit more below, but first some side notes:

  • I have disabled a lot of automatic conversion in various places, for testing purposes, so I wouldn't actually merge this PR right now. Currently a very limited set of things are automatically converted into Python (nothing, numbers, strings and tuples) and conversion back to Julia is completely disabled.
  • I have consolidated the functionality which deals directly with the libpython C API into files under libpython/. In particular, there are some auto-generated wrappers around many functions and global objects from libpython. Structs which mirror libpython structs are also there. I have used the naming convention from Julia and prepended "C" to all the names. For example, what was PyObject_struct I have taken the liberty to rename CPyObject.
  • libpython/extensions.jl contains extensions to the C API, for example allowing conversion from Julia strings to Python strings and back. In particular, there is CPyObject_From(x) which converts from julia to python. Then simply PyObject(x) = PyObject(CPyObject_From(x)) (see conversions.jl).
  • In some places (e.g. pystr) I have re-implemented things using the C API instead of the higher level PyCall API, because this is more direct, invokes Julia's exception handler less, and is less susceptible to changes in the PyCall API, in particular with changes to automatic conversion.

Aside from the above, the file jlwrap.jl contains the main piece of the implementation.

  • All pyjlwrap objects are instances of the struct CPyJlWrapObject.
  • There is a hierarchy of types for these, called CPyJlWrap*_Type, where CPyJlWrap_Type is the root. The functionality of each type should best represent the translation between Julia and Python semantics, so for example an object of type CPyJlWrapBufferedIO_Type translates Julia Base.IO semantics to python io.BufferedIO semantics.
  • An instance of a particular type can be made with PyObject(CPyJlWrap_New(t, x)) where t is the type and x is the Julia value being wrapped.
  • Alternatively PyObject(CPyJlWrap_From(x)) (alternatively pyjlwrap(x)) selects the type appropriately based on the type of x, so numbers get wrapped with some subtype of CPyJlWrapNumber_Type, etc.
  • The types created so far correspond to the abstract base classes from numbers, io and collections.abc. The types are all registered to the corresponding ABC, so for example jlwrap(3//2) is an instance of numbers.Rational. The numbers and io interfaces are fully implemented (I think). The collections.abc interface is less complete.

Things to do:

  • Complete the collections.abc interface.
  • Implement the buffer protocol when wrapping a Julia Array or String etc.
  • Currently binary operations/comparisons only succeed when both operands are pyjlwraps. What should we do when only one is? We could try converting the pyjlwrap operand to Python, or convert the other operand to Julia, or try one then the other?
  • Re-enable the conversions (but that's a separate topic).

@cjdoris cjdoris closed this Jul 2, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant