8 - Interfacing Julia with other languages
Julia can natively call C and Fortran libraries and, through packages, C++, R (1,2) and Python. This allows Julia to use the huge number of libraries of these more established languages.
C
mylib.h:
mylib.c:
Compiled with:
gcc -o mylib.o -c mylib.c
gcc -shared -o libmylib.so mylib.o -lm -fPIC
Use in julia with:
Python
Use Python in Julia
We show here an example with Python. The following code converts an ODS spreadsheet in a Julia DataFrame, using the Python ezodf module (of course this have to be already be available in the local installation of python):
The first thing, is to declare we are using PyCall and to @pyimport
the python module we want to work with. We can then directly call its functions with the usual Python syntax module.function()
.
Type conversions are automatically performed for numeric, boolean, string, IO stream, date/period, and function types, along with tuples, arrays/lists, and dictionaries of these types.
Other types are instead converted to the generic PyObject type, as it is the case for the destDoc
object returned by the module function.
You can then access its attributes and methods with myPyObject.attibute
and myPyObject.method()
respectively.
Use Julia in Python
The other way around, embedding Julia code in a Python script or terminal, is equally of interest, as it allows in many cases to benefit of substantial performance gains for Python programmers, and it may be easier than embedding C or C++ code.
We show here how to achieve it using the PyJulia Python package, a Python interface to Julia, with the warning that, at time of writing, it is not as polished, simple and stable solution as PyCall, the Julia interface to Python.
Installation
Before installing PyJulia
, be sure that the PyCall
module is installed in Julia and that it is using the same Python version as the one from which you want to embed the Julia code (eventually, run ENV["PYTHON"]="/path/to/python"; using Pkg; Pkg.build("PyCall");
from Julia to change its underlying Python interpreter).
At the moment only the pip
package manager is supported in Python to install the PyJulia
package (conda
support should come soon). Please notice that the name of the package in pip
is julia
, not PyJulia
:
If we have multiple Julia versions, we can specify the one to use in Python passing julia="/path/to/julia/binary/executable"
(e.g. julia = "/home/myUser/lib/julia-1.1.0/bin/julia"
) to the install()
function.
Usage
To obtain an interface to Julia just run:
The compiled_module=False
in the Julia constructor is a workaround to the common situation when the Python interpreter is statically linked to libpython
, but it will slow down interactive experience, as it will disable Julia packages pre-compilation, and every time we will use a module for the first time, this will need to be compiled first. Other, more efficient but also more complicate, workarounds are given in the package documentation, under the Troubleshooting section.
We can now access Julia in multiple ways.
We may want for example define all our functions in a Julia script and "include" it. Let's assume juliaScript.jl
is made of the following Julia code:
We can access its functions in Python with:
As in calling Python from Julia, also here we can pass to the functions and retrieve complex data types without warring too much about the conversion. Note that now we get the Julia way on indexing (1-based).
We can otherwise embed Julia code directly in Python using the Julia eval()
function:
We can then call the above function in Python as jl.funnyProd(2,3)
.
What if, instead, we want to run the function in broadcasted mode, i.e. applying the function for each elements of a given array ? In Julia we could use the dot notation, e.g. funnyProd.([2,3],[4,5])
(this would apply the funnyProd()
function first to the (2,4)
arguments and then to the (3,5)
ones and collecting the two results in the array [8,15]
). The problem is that this would not be valid Python syntax. + In cases like this one, when we can't simply call a Julia function using Python syntax, we can still rely to the same Julia eval
function we used to define the Python function to also call it: jl.eval("funnyProd.([2,3],[4,5])")
Finally, we can access any module available in Julia with from julia import ModuleName
, and in particular we can set and access global Julia variables using the Main
module.
R
Use Julia in R
To embed Julia code within a R workflow, we can use the R package JuliaCall.
Installation
Install the Julia binaries for your OS from JuliaLang. Then, in R:
That's all.
Usage
Note that, differently than PyJulia
, the "setup" function need to be called every time we start a new R section, not just when we install the JuliaCall
package. If we don't have julia
in the path of our system, or if we have multiple versions and we want to specify the one to work with, we can pass the JULIA_HOME = "/path/to/julia/binary/executable/directory"
(e.g. JULIA_HOME = "/home/myUser/lib/julia-1.1.0/bin"
) parameter to the julia_setup
call.
JuliaCall
depends for some things (like object conversion between Julia and R) from the Julia RCall
package. If we don't already have it installed in Julia, it will try to install it automatically.
As expected, also JuliaCall
offers multiple ways to access Julia in R.
Let's assume we have all our Julia functions in a file. We are going to reuse the juliaScript.jl
script we used in PyJulia
:
we can access its functions in R with:
Concerning the last example, it highlights the usage of the pipe
operator that is very common in R. The %>J%
syntax is a special "version" of it, provided by JuliaCall
, allowing to mix Julia functions in a left-to-right data transformation workflow.
We can otherwise embed Julia code directly in R using the julia_eval()
function:
We can then call the above function in R either as funnyProdR(2,3)
, julia_eval("funnyProd(2,3)")
or julia_call("funnyProd",2,3)
.
While other "convenience" functions are provided by the package, using julia_eval
and julia_call
should suffix to accomplish any task we may need in Julia.
While an updated, expanded and revised version of this chapter is available in "Chapter 7 - Interfacing Julia with Other Languages" of Antonello Lobianco (2019), "Julia Quick Syntax Reference", Apress, this tutorial remains in active development.
Last updated