# 8 - Interfacing Julia with other languages

Julia can natively call [C and Fortran libraries](http://docs.julialang.org/en/stable/manual/calling-c-and-fortran-code/) and, through packages, [C++](https://github.com/JuliaInterop/CxxWrap.jl), R ([1](https://github.com/JuliaInterop/RCall.jl),[2](https://github.com/lgautier/Rif.jl)) and [Python](https://github.com/JuliaPy/PyCall.jl).\
This allows Julia to use the huge number of libraries of these more established languages.

## C

mylib.h:

```
#ifndef _MYLIB_H_
#define _MYLIB_H_

extern float iplustwo (float i);
extern float getTen ();
```

mylib.c:

```
float
iplustwo (float i){
 return i+2;
}
```

Compiled with:

* `gcc -o mylib.o -c mylib.c`
* `gcc -shared -o libmylib.so mylib.o -lm -fPIC`

Use in julia with:

```julia
i = 2
const mylib = joinpath(@__DIR__, "libmylib.so")
j = ccall((:iplustwo, mylib), Float32, (Float32,), i)
```

## 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](https://github.com/T0ha/ezodf) module (of course this have to be already be available in the local installation of python):

```julia
using PyCall
using DataFrames

const ez = pyimport("ezodf")  # Equiv. of Python `import ezodf as ez`
destDoc = ez.newdoc(doctype="ods", filename="anOdsSheet.ods")
sheet = ez.Sheet("Sheet1", size=(10, 10))
destDoc.sheets.append(sheet)
dcell1 = get(sheet,(2,3)) # Equiv. of Python `dcell1 = sheet[(2,3)]`. This is cell "D3" !
dcell1.set_value("Hello")
get(sheet,"A9").set_value(10.5) # Equiv. of Python `sheet['A9'].set_value(10.5)`
destDoc.backup = false
destDoc.save()
```

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](https://github.com/JuliaPy/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`:

```python
$ python3 -m pip install --user julia
>>> import julia
>>> julia.install()
```

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:

```python
>>> import julia;
>>> jl = julia.Julia(compiled_modules=False)
```

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](https://pyjulia.readthedocs.io/en/stable/troubleshooting.html).

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:

```julia
function helloWorld()
    println("Hello World!")
end
function sumMyArgs(i, j)
  return i+j
end
function getNElement(n)
  a = [0,1,2,3,4,5,6,7,8,9]
  return a[n]
end
```

We can access its functions in Python with:

```python
>>>> jl.include("juliaScript.jl")
>>>> jl.helloWorld() # Prints `Hello World!``
>>>> a = jl.sumMyArgs([1,2,3],[4,5,6]) # Returns `array([5, 7, 9], dtype=int64)``
>>>> b = jl.getNElement(1) # Returns `0`, the "first" element for Julia
```

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:

```python
>>> jl.eval("""
... function funnyProd(is, js)
...   prod = 0
...   for i in 1:is
...     for j in 1:js
...       prod += 1
...     end
...   end
...   return prod
... end
... """)
```

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](https://github.com/Non-Contradiction/JuliaCall).

#### Installation

Install the Julia binaries for your OS from [JuliaLang](https://julialang.org/). Then, in R:

```r
> install.packages("JuliaCall")
```

That's all.

#### Usage

```
> library(JuliaCall)
> julia_setup()
```

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`:

```julia
function helloWorld()
    println("Hello World!")
end
function sumMyArgs(i, j)
  return i+j
end
function getNElement(n)
  a = [0,1,2,3,4,5,6,7,8,9]
  return a[n]
end
```

we can access its functions in R with:

```r
> julia_source("juliaScript.jl") # Include the file
> julia_eval("helloWorld()") # Prints `Hello World!` and returns NULL
> a <- julia_call("sumMyArgs",c(1,2,3),c(4,5,6)) # Returns `[1] 5 7 9`
> as.integer(1) %>J% getNElement -> b  # Returns `0`, the "first" element for both Julia and R
```

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:

```
> funnyProdR <- julia_eval('
+   function funnyProd(is, js)
+     prod = 0
+       for i in 1:is
+         for j in 1:js
+           prod += 1
+         end
+       end
+       return prod
+     end
+ ')
```

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*](https://julia-book.com)*, this tutorial remains in active development.*


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://syl1.gitbook.io/julia-language-a-concise-tutorial/language-core/interfacing-julia-with-other-languages.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
