- Notifications
You must be signed in to change notification settings - Fork1
A bridge between Nim-lang and Julia !
SciNim/nimjl
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
- Install Julia version 1.5.3 or above. Version 1.6.6 or above is recommended.
juliaexecutable must be in your path.- By-default,
nimjlwill use Julia'sSys.BINDIRparent directory as the installation folder of Julia. - If you want
nimjlto use a specific Julia installation, set the environment variableJULIA_PATHto the root of the installation folder.
- By-default,
- Run
nimble installornimble develop
After this steps,$JULIA_PATH/include should points to Julia header and$JULIA_PATH/lib should point tolibjulia.so
You can also install Julia locally by runningnimble install julia, in that case it will install Julia in thethird_party folder
How to embed Julia w/ C :
https://docs.julialang.org/en/v1/manual/embedding/index.html#Working-with-Arrays-1
https://github.com/JuliaLang/julia/tree/master/test/embedding
Read the Scinim getting-startedchapter on Nimjl
legacy/folder contains previous experiment and examples of wrapping in C.tests/testfull.nimis thet test suiteexamples/contains several examples
Julia is mostly oriented towards numerical computing so Arrays are THE most important data structure to support
Mostly quality-of-life improvements, especially when handling arrays.
- Improve Julia Arrays interop. from Nim.
- Supports complex Arrays
- map / apply / reduce /fold
- Support Julia chaining syntax
- Add support for Enum types
Avoid using global scope for Julia function call. Always have everything inse proc / func. It's good practice anyway
Value conversion Nim -> Julia are doneby copy.
- Arrays are an exception to this rule and can be created from buffer / are accessible using a buffer.
Value conversion Julia -> Nim s always doneby copy
- When using Arrays you can access the buffer as
ptr UncheckedArrayof the Julia Arrays withrawData(). - Using
to(seq[T])orto(Tensor[T])perform acopyMemofjlArray.rawData()in your seq/Tensor
- When using Arrays you can access the buffer as
Julia allocated arrays only goes up to 3 dimensions (but Arrays can be allocated in Nim)
Linux / WSL supports only
- Windows dynamic library linking is different than Linux.
- If you need Windows support, consider opening an issue or a PR :).
- Otherwise, just use WSL
Here is the basic example:
import nimjlprocmain()=Julia.init()# Initialize Julia VM. Subsequent call will be ignoredvar myval=4.0'f64# Call Julia function "sqrt" and convert the result to a floatvar res=Julia.sqrt(myval).to(float64)echo res# 2.0whenisMainModule:main()
JlVmExit() seems optionnal. It's present in the C API but not calling it doesn't seem to cause any problem.
Nonetheless, if you use OS resources from Julia it is probably better to call Julia.exit() / JlVmExit() for a clean exit.
For faster startup times, you can create and load precompiled Julia system images:
import nimjl/sysimage# Create a system image with packages and codecreateAppSysImage("myapp.so", packages= ["DataFrames","Plots"], sourceFiles= ["init.jl"], sourceDirs= ["src/"]# Includes all .jl files recursively)# Initialize Julia with the custom imageinitWithSysImage("myapp.so")
System images eliminate recompilation overhead and allow distributing precompiled binaries.
Enhanced error messages with Julia stack traces in debug mode:
try:discardJulia.myFunction(42)exceptJlErroras e:echo"Julia error:", e.msg# Includes context and stack traceexceptJlInitErroras e:echo"VM not initialized:", e.msg
- It is now possible to embed Julia files inside a Nim compiled binary to easily distribute Julia code. To make distribution possible, an API to call
Pkg.add("...")has also been addedwith version number easy to specify.
import nimjlJulia.init:Pkg:add(name="Polynomials", version="3.0.0")add(name="LinearAlgebra")add("DSP")add(name="Wavelets", version="0.9.4")Embed:# embed all files with '*.jl' extension in folder ``JuliaToolBox/``dir("JuliaToolBox/")# embed all files with '*.jl' extension in the folder of he source file (at compilation) i.e. ``getProjectPath()``thisDir()# embed specific file; path should be relative to ``getProjectPath()``file("localfile.jl")
Note that the order of the file matters.See examples/ex09_embed_file.nim for a concrete example.
Take a look attests/ orexamples/ folder for typical examples.
- You can use Pkg: activate() to setup a virtual env
- Alternatively, you can embed a Julia file that setup your environment and dependencies and embed itfirst.
- Because files are evaluated in the order they are embedded, it will deterine the env for all the other files.
nimjl supports cross-compilation for scenarios where you need to compile for a different architecture than your host machine (e.g., compiling on x86_64 for ARM64, or on macOS for Linux).
Important: Cross-compilation requires the target architecture Julia libraries to be available on your build machine. You must specify the path using either:
- The
-d:JuliaPath="/path/to/target-julia"compile flag, OR - The
JULIA_PATHenvironment variable
Enable cross-compilation mode by adding the-d:nimjl_cross_compile flag:
# Using compile flag (recommended for explicit control)nim c -d:nimjl_cross_compile \ -d:JuliaPath="/path/to/arm64-julia" \ --cpu:arm64 --os:linux \ myapp.nim# Using environment variableexport JULIA_PATH=/path/to/arm64-julianim c -d:nimjl_cross_compile --cpu:arm64 --os:linux myapp.nim
Normal Mode (default):
- Queries the Julia binary at compile time:
julia -E VERSION - Most reliable, but requires Julia to be installed and runnable on the host
- Auto-detects Julia from
juliain PATH if not specified
Cross-Compilation Mode (-d:nimjl_cross_compile):
- Extracts Julia version from the library filename instead
- macOS:
libjulia.1.11.7.dylib→ version 1.11.7 - Linux:
libjulia.so.1.11.7→ version 1.11.7 - Allows compilation when target Julia binary isn't runnable on host
- Requires explicit path via
-d:JuliaPathorJULIA_PATHenvironment variable
# Install ARM64 Julia libraries in a known locationexport JULIA_PATH=/path/to/arm64-julia# Cross-compile with Nimnim c -d:nimjl_cross_compile \ --cpu:arm64 \ --os:linux \ -d:JuliaPath="/path/to/arm64-julia" \ myapp.nim
To validate cross-compilation worked correctly:
Check library dependencies:
# On Linux:ldd myapp| grep julia# On macOS:otool -L myapp| grep julia
Should show paths to the correct Julia libraries
Verify architecture:
# On Linux:file myapp# On macOS:lipo -info myapp
Should show the target architecture (e.g., ARM64, x86_64)
Check embedded version:
strings myapp| grep"Nimjl> Using"
Should show the Julia version extracted from the library
Runtime test:Transfer the binary to the target platform and run it. If Julia initialization succeeds, the cross-compilation worked correctly.
Most error will come from incorrect type passed between Julia and Nim. Check function interface and return type first.
If you have random segfault that are non-reproductible, that may be a cause of the Julia GC cleaning memory that Nim uses. Consider using jlGcRoot.
If you do not work with fixed version package for Julia, you are at risk of code breaking when packages are updated / upgraded.
This project is released under MIT License.
About
A bridge between Nim-lang and Julia !
Topics
Resources
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Uh oh!
There was an error while loading.Please reload this page.