# How to Integrate Julia Code in Nelson Using the julia_engine Module

> Integrate Julia code in Nelson using julia_engine. Execute Julia expressions and scripts with jlrun and jlrunfile, passing and retrieving data seamlessly. 

- Repository: [The Nelson Programming Language/nelson](https://github.com/nelson-lang/nelson)
- Tags: how-to-guide
- Published: 2026-03-08

---

**Use the `jlrun` and `jlrunfile` functions from the `julia_engine` module to execute Julia expressions and scripts directly within Nelson, passing data via name-value pairs and retrieving results as Nelson variables.**

The nelson-lang/nelson repository provides a native `julia_engine` module that embeds a full Julia runtime inside the Nelson interpreter. This integration allows you to seamlessly integrate Julia code in Nelson, enabling you to execute arbitrary Julia expressions, run external scripts, and exchange data between the two environments without leaving the Nelson console.

## Architecture of the julia_engine Module

The integration works through a thin C++ bridge that loads the Julia shared library and manages data conversion between Nelson's `ArrayOf` type and Julia's native types.

### Engine Initialization

When you first call a Julia function, the engine initializes automatically via `initializeJuliaEngine` in [`modules/julia_engine/src/cpp/JuliaEngine.cpp`](https://github.com/nelson-lang/nelson/blob/main/modules/julia_engine/src/cpp/JuliaEngine.cpp). This process:

1. Checks if the Julia library is already loaded
2. Reads `standardInOutRedirection.jl` to redirect Julia's stdout/stderr to Nelson's console
3. Starts the Julia runtime via `NLSjl_init`

The module loader in `modules/julia_engine/loader.m` registers the `julia_engine` module at Nelson startup unless `--without_julia` is passed.

### Data Flow and Variable Conversion

When you execute Julia code, the following data flow occurs:

1. **Input**: Name-value pairs from Nelson become global variables in Julia's `Main` module via `jl_create_main_global_variable`
2. **Execution**: The code evaluates via `NLSjl_eval_string` (for strings) or `include()` (for files)
3. **Output**: Requested variables are retrieved from `Main` using `NLSjl_get_global` and converted to `ArrayOf` via `jl_value_tToArrayOf` in [`JuliaTypesHelpers.cpp`](https://github.com/nelson-lang/nelson/blob/main/JuliaTypesHelpers.cpp)

## Executing Julia Code with jlrun

The `jlrun` function provides the primary interface for executing Julia expressions from Nelson.

### Running Simple Expressions

To execute a Julia expression and capture the result:

```matlab
% Execute a Julia command that returns a matrix
M = jlrun('reshape(1:9, 3, 3)', ["M"]);
disp(M);

```

The [`jlrunBuiltin.cpp`](https://github.com/nelson-lang/nelson/blob/main/jlrunBuiltin.cpp) file handles argument parsing, separating the code string from output variable names and name-value pairs, then forwards to [`JuliaRun.cpp`](https://github.com/nelson-lang/nelson/blob/main/JuliaRun.cpp) for execution.

### Passing Data from Nelson to Julia

You can pass Nelson variables to Julia using name-value pairs:

```matlab
% Create a Nelson array
A = int64([1; 2; 3]);

% Pass it to Julia and retrieve a transformed version
B = jlrun('B = A .* 2', ["B"], "A", A);
disp(B);

```

In this example:
- `"A", A` creates a Julia global variable `A` containing the Nelson data
- The Julia code computes `B = A .* 2`
- `"B"` in the output list requests retrieval of the `B` variable back to Nelson

## Running Julia Scripts with jlrunfile

For larger Julia programs, use `jlrunfile` to execute entire scripts:

```matlab
% Run the script and retrieve three variables A, B, C
[a, b, c] = jlrunfile('test_jlrunfile.jl', ["A","B","C"]);

```

The [`jlrunfileBuiltin.cpp`](https://github.com/nelson-lang/nelson/blob/main/jlrunfileBuiltin.cpp) interface parses the filename and arguments, then [`JuliaRunFile.cpp`](https://github.com/nelson-lang/nelson/blob/main/JuliaRunFile.cpp) executes the script using Julia's `include()` function. The implementation follows the same variable injection and retrieval pattern as `jlrun`.

Consider this example script:

```julia

# test_jlrunfile.jl

A = [1;2;3];
B = [4;5;6];
C = [15.0 25.0 35.0; 17.0 27.0 37.0; 19.0 29.0 39.0];
println("Hello from Julia")
println(C)

```

After execution, `a`, `b`, and `c` contain the respective arrays in Nelson's native format.

## Configuring the Julia Environment with jlenv

Before executing any Julia code, you can control which Julia installation Nelson uses via `jlenv`:

```matlab
% Query current environment
env = jlenv()

% Change to a custom Julia executable
jlenv('Version', '/opt/julia-1.11.0/bin/julia');

```

The `jlenv.m` function in `modules/julia_engine/functions/jlenv.m` detects the current Julia environment, performs version and architecture checks, and updates the internal `JuliaEnvironment` singleton. **Important**: You must call `jlenv` before the first Julia execution, as the library cannot be unloaded or switched once `initializeJuliaEngine` has loaded the shared library.

## Complete Example: Differential Equations

The repository includes a practical example demonstrating real-world Julia package usage:

```matlab
% Run a Julia script that solves the Lotka-Volterra system
jlrunfile('example_DifferentialEquations.jl');

```

The script `example_DifferentialEquations.jl` installs the `DifferentialEquations` package, solves an ODE system, and prints results. All standard output appears in the Nelson console, allowing seamless integration of Julia's scientific computing ecosystem into Nelson workflows.

## Summary

- The **julia_engine** module embeds a full Julia runtime inside Nelson via a C++ bridge in [`JuliaEngine.cpp`](https://github.com/nelson-lang/nelson/blob/main/JuliaEngine.cpp).
- Use **`jlrun`** to execute Julia expressions and **`jlrunfile`** to run complete scripts, both supporting bidirectional data transfer via name-value pairs.
- Data conversion happens automatically through [`JuliaTypesHelpers.cpp`](https://github.com/nelson-lang/nelson/blob/main/JuliaTypesHelpers.cpp), translating between Nelson `ArrayOf` and Julia types.
- Configure the Julia installation using **`jlenv`** before first execution to specify custom executables or library paths.
- The integration supports complex workflows including package installation and scientific computing, as demonstrated in the `example_DifferentialEquations.jl` sample.

## Frequently Asked Questions

### How do I pass multiple variables from Nelson to Julia?

Use consecutive name-value pairs in `jlrun` or `jlrunfile`. For example: `jlrun('C = A + B', ["C"], "A", A, "B", B)`. The C++ layer in [`JuliaRun.cpp`](https://github.com/nelson-lang/nelson/blob/main/JuliaRun.cpp) creates corresponding globals in Julia's `Main` module for each pair.

### Can I switch Julia versions after Nelson has started the engine?

No. Once `initializeJuliaEngine` in [`JuliaEngine.cpp`](https://github.com/nelson-lang/nelson/blob/main/JuliaEngine.cpp) loads the Julia shared library, the runtime cannot be unloaded or switched. You must call `jlenv` to configure the path before executing any Julia code, or restart Nelson to change versions.

### What Julia types are supported for data exchange?

The conversion layer in [`JuliaTypesHelpers.cpp`](https://github.com/nelson-lang/nelson/blob/main/JuliaTypesHelpers.cpp) handles primitive numeric types, arrays, and matrices. Complex numbers and strings are also supported. When you request an output variable, `jl_value_tToArrayOf` converts the Julia object back to Nelson's native `ArrayOf` structure.

### How do I capture standard output from Julia scripts?

Standard output redirection happens automatically via `standardInOutRedirection.jl`, which the engine loads during initialization in [`JuliaEngine.cpp`](https://github.com/nelson-lang/nelson/blob/main/JuliaEngine.cpp). Any `println` or `print` statements in your Julia code appear directly in the Nelson console without additional configuration.