Звонок Джулии из Луа

Звонок Джулии из Луа

Этот пример кода ранее появлялся назапись в блоге Адитьи, с одной незначительной корректировкой. Я попытался запустить его на Debian 10 (buster), но он не запустился со следующей ошибкой.

texlua julia.lua
ERROR: could not load library "/usr/lib/x86_64-linux-gnu/../bin/../lib/x86_64-linux-gnu/julia/sys.so"
/usr/lib/x86_64-linux-gnu/../bin/../lib/x86_64-linux-gnu/julia/sys.so: cannot open shared object file: No such file or directory

Я пробовал это как с версией Julia по умолчанию 1.0.3+dfsg-4, так и с текущей нестабильной версией 1.1.1+dfsg-1. В обоих случаях это приводило к ошибке, показанной выше. Я также использую бэкпорт TeX Live 2019 из нестабильной версии Debian (Debian 10/buster имеет только предварительную версию) с LuaTeX 1.10.0.

Два разных человека сообщают, что этот код работает у них на Arch Linux. Один из них — Адитья.

Процитирую его из чата:

В моей системе библиотека, которую следует загрузить, — это libjulia.so, она расположена по адресу /usr/lib/libjulia.so.

В моей системе Debian julia/sys.soон установлен, но я не уверен, почему он не обнаруживается.

dlocate julia/sys.so
libjulia1: /usr/lib/x86_64-linux-gnu/julia/sys.so

Ниже приведен код.

local ffi = require("ffi")
local JULIA = ffi.load("julia", true)

ffi.cdef [[
void jl_init__threading(void);
typedef struct _jl_value_t jl_value_t;
jl_value_t *jl_eval_string(const char*);
]]

JULIA.jl_init__threading()

code = [[
x = [1 2 3]'
A = [1 0 1; 0 1 1; 1 1 0]

y = x'*A*x

print(y[1])
]]

JULIA.jl_eval_string(code)

решение1

Для работы Julia требуется системная среда выполнения sys.jl. Интерпретатор Julia поставляется с предварительно скомпилированной версией этой среды выполнения, которая выгружается в sys.so. Я думаю, что на разрешение пути к sys.soможно как-то повлиять, задав переменные окружения, но мне не удалось выяснить, как это сделать. Другой альтернативой является указание функции jl_initна путь к образу системы с помощью jl_init_with_image.

local ffi = require("ffi")
local JULIA = ffi.load("julia", true)

ffi.cdef [[
void jl_init_with_image__threading(const char *julia_bindir,
                                   const char *image_relative_path);
typedef struct _jl_value_t jl_value_t;
jl_value_t *jl_eval_string(const char*);
]]

JULIA.jl_init_with_image__threading("/usr/lib/x86_64-linux-gnu/julia/", "sys.so")

code = [[
x = [1 2 3]'
A = [1 0 1; 0 1 1; 1 1 0]

y = x'*A*x

print(y[1])
]]

JULIA.jl_eval_string(code)

Я сохранил этот файл как /tmp/julia/test.luaи запустил его в контейнере Docker, используя следующие команды:

user@host:~$ sudo docker run -v /usr/local/texlive/2019/:/usr/local/texlive/2019/:ro -v /tmp/julia/:/tmp/julia/ -it --rm debian:buster
root@9903c6e0ca52:/# export PATH=/usr/local/texlive/2019/bin/x86_64-linux/:$PATH
root@9903c6e0ca52:/# apt-get update
[...]
root@9903c6e0ca52:/# apt-get install --no-install-recommends julia libjulia-dev
[...]
root@9903c6e0ca52:/# texlua /tmp/julia/test.lua
23root@9903c6e0ca52:/#

До 23последней root@9903c6e0ca52строки — это вывод от Julia. Это то же самое, что я получаю от интерактивного сеанса Julia:

julia> x = [1 2 3]'
3×1 LinearAlgebra.Adjoint{Int64,Array{Int64,2}}:
 1
 2
 3

julia> A = [1 0 1; 0 1 1; 1 1 0]
3×3 Array{Int64,2}:
 1  0  1
 0  1  1
 1  1  0

julia> y = x'*A*x
1×1 Array{Int64,2}:
 23

julia> print(y[1])
23

Связанный контент