This directory contains example projects demonstrating how to use RustCall.jl for Julia-Rust interoperability.
Before running the examples, ensure you have:
- Julia 1.12+ installed
- Rust (stable) with
cargoinstalled# Check Rust installation rustc --version cargo --version - RustCall.jl installed with
Pkg.add("RustCall")or developed locally from this checkout
| Example | Description | Difficulty | Key Features |
|---|---|---|---|
| MyExample.jl | Julia package using rust"" string literal |
Beginner | Inline Rust code, basic FFI |
| sample_crate | Rust crate using #[julia] attribute |
Intermediate | External crate, @rust_crate macro |
| sample_crate_pyo3 | Dual bindings for Julia and Python | Advanced | PyO3 integration, feature flags |
If you're a Julia user who wants to call Rust code, start with MyExample.jl:
using Pkg
# Navigate to the example
cd("examples/MyExample.jl")
# Activate and set up the environment
Pkg.activate(".")
Pkg.instantiate()
# Use the example
using MyExample
add_numbers(Int32(10), Int32(20)) # => 30If you're a Rust developer who wants to expose your code to Julia, start with sample_crate:
using RustCall
# Load the sample crate and keep the returned bindings value
sample_crate_path = joinpath(dirname(dirname(pathof(RustCall))), "examples", "sample_crate")
const SampleCrate = @rust_crate sample_crate_path
# Call Rust functions
SampleCrate.add(Int32(2), Int32(3)) # => 5
SampleCrate.fibonacci(UInt32(10)) # => 55A Julia package that demonstrates using the rust"" string literal to write Rust code directly in Julia.
Features demonstrated:
- Inline Rust code with
rust"..."string literals - Basic numerical operations (add, multiply, fibonacci)
- String processing (word count, reverse)
- Array operations (sum, max)
How to run:
cd examples/MyExample.jl
julia --project=. -e 'using Pkg; Pkg.instantiate()'
julia --project=. test/runtests.jlFor normal use, Pkg.instantiate() resolves RustCall.jl from Julia's General registry. Use Pkg.develop(path="../../") only when testing local changes from this checkout.
A standalone Rust crate demonstrating the #[julia] attribute from juliacall_macros.
Features demonstrated:
#[julia]attribute for automatic FFI generationResult<T, E>andOption<T>type handling- Struct definitions with methods
- Property access syntax for struct fields
How to build:
cd examples/sample_crate
cargo build --releaseHow to use from Julia:
using RustCall
const SampleCrate = @rust_crate "/path/to/examples/sample_crate"
# Functions
SampleCrate.add(Int32(1), Int32(2))
# Structs with property access
p = SampleCrate.Point(3.0, 4.0)
p isa SampleCrate.Point # => true
p.x # => 3.0
p.y # => 4.0
SampleCrate.distance_from_origin(p) # => 5.0A Rust crate demonstrating dual bindings for both Julia and Python using feature flags.
Features demonstrated:
- Coexistence of
#[julia]and PyO3 in a single crate - Feature flags to separate Julia/Python builds
- Shared core logic between both languages
- Proper separation of concerns
How to build for Julia:
cd examples/sample_crate_pyo3
cargo build --releaseHow to build for Python:
cd examples/sample_crate_pyo3
pip install maturin
maturin build --features pythonHow to use from Julia:
using RustCall
const SampleCratePyo3 = @rust_crate "/path/to/examples/sample_crate_pyo3"
SampleCratePyo3.add(Int32(2), Int32(3)) # => 5How to use from Python:
import sample_crate_pyo3 as m
m.add(2, 3) # => 5We recommend learning RustCall.jl in this order:
-
Start with MyExample.jl
- Learn how to write inline Rust code
- Understand basic type mappings (Int32 ↔ i32, Float64 ↔ f64)
- Practice calling Rust functions from Julia
-
Move to sample_crate
- Learn about the
#[julia]attribute - Understand
@rust_cratefor external crates - Explore struct handling and property access
- Learn about
Result<T, E>andOption<T>support
- Learn about the
-
Explore sample_crate_pyo3 (optional)
- Learn how to create dual Julia/Python bindings
- Understand feature flags for conditional compilation
- See how to share core logic between languages
-
Read the documentation
If you see "rustc not found in PATH", install Rust from rustup.rs.
Try clearing the cache and rebuilding:
using RustCall
clear_cache()When using @rust_crate, the returned bindings object wraps a generated runtime module whose default name is the crate name converted to PascalCase.
Example: sample_crate → SampleCrate
You can override that internal runtime module name with name=, while still using the value returned by @rust_crate:
const bindings = @rust_crate "/path/to/crate" name="MyCustomName"