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