1
0
Fork
You've already forked pythonlib
0
fork of Jane Street repo with added functionality
OCaml 82.9%
Jupyter Notebook 9.8%
Python 5.3%
C 1.1%
Shell 0.8%
Other 0.1%
Find a file
2025年03月24日 19:00:26 +01:00
example-native-builtin Extends Pyml Bigarray support to Pythonlib 2025年03月24日 19:00:26 +01:00
example-native-loaded Extends Pyml Bigarray support to Pythonlib 2025年03月24日 19:00:26 +01:00
example-ok Extends Pyml Bigarray support to Pythonlib 2025年03月24日 19:00:26 +01:00
examples added ability to use ppx's (including ppx-python\!) in jupyter 2025年02月27日 01:56:21 +01:00
src Extends Pyml Bigarray support to Pythonlib 2025年03月24日 19:00:26 +01:00
.gitignore added native REPL example and nqueens notebook 2025年03月15日 06:07:24 +01:00
.ocamlformat v0.17~preview.128.37+01 2023年08月30日 10:23:16 +01:00
CONTRIBUTING.md v0.13-preview.120.47+86 2019年07月31日 12:50:10 +01:00
dune-project added native REPL example and nqueens notebook 2025年03月15日 06:07:24 +01:00
LICENSE.md v0.17~preview.129.07+242 2024年02月06日 16:13:48 +00:00
Makefile v0.13-preview.120.47+86 2019年07月31日 12:50:10 +01:00
pythonlib.opam added ability to use ppx's (including ppx-python\!) in jupyter 2025年02月27日 01:56:21 +01:00
README.md Extends Pyml Bigarray support to Pythonlib 2025年03月24日 19:00:26 +01:00

pythonlib makes it easier to write wrappers around ocaml functions so that they can be called from python.

Resurrected!

The Jane Street repo has been archived so it appears there will be no more development or maintenance of it. The more recent version doesn't compile but there is an outstanding PR addressing a few problems and this fork incorporates that PR. Additionally this JS blog on Pythonlib mentions in the conclusion a limitation - the PPX cannot be used in a Jupyter/Ipython context so there was no convenient interchange of OCaml record types. That limitation has been removed; after decorating a type declaration with [@@deriving python] one can then register a monomorphic type with %add_type <t> and thereafter get automatic conversions. The ppx-python package repo looks to be still active.

The originating repository is further extended with parameterized types: records and regular variants (disjoint unions) in any combination of up to 5 parameters can now be registered via %add_type. It's a dirty Obj.magic hack though.

On the back of that is the addition of ('a, 'b, 'c) Bigarray.Genarray.t which is distinguished in Pyml by allowing for non-copy sharing to/from Python.

See the notebook example-ok/ex1.ipynb for examples.

Lastly, the blog article suggests better performance with a native compilation. There are two further example directories implementing this: example-native-builtin and example-native-loaded. The builtin exists because the 4.14.2 switch used for these developments appears to have problems with ocamlnat and the interactive loading of libraries. The workaround has been to include all the libraries this library depends on in a monolithic build. This results in some explicit code references (brittle) and continued inability to load further libraries/PPX's. But it works to run the notebook examples. The loaded variation is the minimal build/all-else-runtime-loaded version that will probably work for non-broken ocamlnat installations, which then allows user specified additional libraries/PPX's and is without the brittleness of hardcoded references. To be tested!

The reformulated examples/ is at example-ok/. First install Python lib via opam install .. Assuming operation is within a suitably equipped local Python environment, after editing the file do . example-ok/build.sh which pip installs a compiled ocaml.so object. Then run jupyter notebook and navigate to the above notebook.

The pip-installed package is put at version 0.0.12 - the online version mentioned in the blog was at 0.0.11 and didn't work in my environment. It appears that was derived from the examples/ directory and included the example_module code as below. The example-ok version has that removed and so provides a suitably minimal ocaml.toploop module.

The original README follows.

Example

This example is taken from the examples directory. The ocaml code defines a function that takes as argument an integer n, performs some computations based on n and return a float value. This function is attached to a newly defined python module named ocaml_module.

open Base
let approx_pi =
 let%map_open.Python_lib n = positional "n" int ~docstring:""
 in
 let sum =
 List.init n ~f:(fun i -> let i = Float.of_int (1 + i) in 1.0 /. (i *. i))
 |> List.reduce_exn ~f:(+.)
 in
 Float.sqrt (sum *. 6.) |> python_of_float
let () =
 if not (Py.is_initialized ())
 then Py.initialize ();
 let mod_ = Py_module.create "example_module" in
 Py_module.set mod_ "approx_pi" approx_pi

This code is compiled to a static library ocaml.so, together with a small C library defining the PyInit_ocaml function that starts the ocaml runtime and exposes the example module. The python code then imports this library and can use the ocaml functions.

# This requires the ocaml.bc.so file to be copied as ocaml.so in the python path
from ocaml import example_module, toploop
# Import the module defined in the ocaml code and run the function.
import ocaml_module
print(ocaml_module.approx_pi(1000))

pythonlib also handles keyword arguments as well as basic types such as int, float, string, list, etc. Further examples can be found in the examples directory.

To compile and run examples:

sh examples/build.sh
python examples/test.py