はじめに
rlua を使って Rust に Lua言語 を組み込む をやりたくなったので、開発環境を用意してみます。
Rust のソースコードから Lua スクリプトを実行します。スクリプトの中で cjson が使えるようにセットアップします。
セットアップ
ベースの Docker イメージ
手元にあった、rust:1.65 の Docker イメージを使います。
$ docker run --rm -it -v $(pwd):/mnt/shared rust:1.65 bash
以下のディストリビューションになっています。
# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 11 (bullseye)"
NAME="Debian GNU/Linux"
VERSION_ID="11"
VERSION="11 (bullseye)"
VERSION_CODENAME=bullseye
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
Lua のインストール
Lua 5.3 を使用します。
この記事では、コマンドは sudo
なしで書いてしまうことにします。
# apt update
# apt install -y lua5.3 liblua5.3-dev
Luarocks のインストール
cjson をインストールするために、luarocks を使用します。
現時点の最新版は 3.9.2 です。
以下のサイトの手順に従ってインストールします。
# cd ~
# wget https://luarocks.org/releases/luarocks-3.9.2.tar.gz
# tar zxpf luarocks-3.9.2.tar.gz
# cd luarocks-3.9.2
# ./configure --with-lua-include=/usr/include/lua5.3
# make
# make install
apt
でもインストールできますが、現時点ではバージョンが 2.4.2 と古いようなので、ソースコードから 3 系のバージョンをインストールすることにします。
# apt search luarocks
Sorting... Done
Full Text Search... Done
luarocks/stable 2.4.2+dfsg-1.1 all
deployment and management system for Lua modules
lua-cjson のインストール
インストール先フォルダの内容を確認しておきます。
# ls /usr/local/share/lua/5.3
luarocks
インストールします。luarocks を make したフォルダではない場所で実行します。
# cd ~
# luarocks install lua-cjson
Installing https://luarocks.org/lua-cjson-2.1.0.10-1.src.rock
lua-cjson 2.1.0.10-1 depends on lua >= 5.1 (5.3-1 provided by VM)
gcc -O2 -fPIC -I/usr/include/lua5.3 -c lua_cjson.c -o lua_cjson.o
gcc -O2 -fPIC -I/usr/include/lua5.3 -c strbuf.c -o strbuf.o
gcc -O2 -fPIC -I/usr/include/lua5.3 -c fpconv.c -o fpconv.o
gcc -shared -o cjson.so lua_cjson.o strbuf.o fpconv.o
No existing manifest. Attempting to rebuild...
lua-cjson 2.1.0.10-1 is now installed in /usr/local (license: MIT)
インストール結果を確認します。
# ls /usr/local/share/lua/5.3
cjson json2lua.lua lua2json.lua luarocks
cjson のフォルダが作成されました。
Rust プロジェクトの作成
Rust のプロジェクトを作成します。
# cd /mnt/shared
# cargo init --bin
# cargo add --no-default-features --features system-lua53 rlua@0.18.0
Cargo.toml は以下のようになっています。
[package]
name = "rluacjson"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rlua = { version = "0.18.0", default-features = false, features = ["system-lua53"] }
ソースコードを記述
main.rs
の内容を書きます。
use rlua::prelude::LuaError;
use rlua::Lua;
fn main() {
println!("Hello, world!");
match run_main() {
Ok(_) => {},
Err(error) => {
eprintln!("{:?}", &error);
}
}
}
fn run_main() -> Result<(), LuaError> {
let lua = Lua::new();
lua.context(|context| {
context.load(r#"
local cjson = require "cjson"
print("Hello, lua.")
local data = cjson.decode('{"greeting":"Hello, cjson."}')
print(data["greeting"])
"#).exec()
})?;
Ok(())
}
ビルド
cargo build
実行
# cargo run
Compiling rluacjson v0.1.0 (/mnt/shared)
Finished dev [unoptimized + debuginfo] target(s) in 0.48s
Running `target/debug/rluacjson`
Hello, world!
Hello, lua.
Hello, cjson.
実行できました。cjson で JSON 文字列の解析と値の参照ができました。
あとで苦しまないために
luarocks を make したフォルダで lua-cjson をインストールした場合
luarocks のインストールを行い、そのフォルダにいる状態で lua-cjson のインストールをしてみます。
# luarocks install lua-cjson
Installing https://luarocks.org/lua-cjson-2.1.0.10-1.src.rock
lua-cjson 2.1.0.10-1 depends on lua >= 5.1 (5.3-1 provided by VM)
gcc -O2 -fPIC -I/usr/include/lua5.3 -c lua_cjson.c -o lua_cjson.o
gcc -O2 -fPIC -I/usr/include/lua5.3 -c strbuf.c -o strbuf.o
gcc -O2 -fPIC -I/usr/include/lua5.3 -c fpconv.c -o fpconv.o
gcc -shared -o cjson.so lua_cjson.o strbuf.o fpconv.o
No existing manifest. Attempting to rebuild...
lua-cjson 2.1.0.10-1 is now installed in /root/luarocks-3.9.2/./lua_modules (license: MIT)
よく見るとインストール先が /root/luarocks-3.9.2/...
となっています。
# ls /usr/local/share/lua/5.3
luarocks
期待するパスには何もインストールされませんでした。luarocks コマンドを実行するときのカレントディレクトリに注意が必要です。
--no-default-features
を指定しなかった場合
人から features に「system-lua53」を指定するのだよと聞いたので、そのようにしてみました。
# cargo add --features system-lua53 rlua@0.18.0
# cargo build
Updating crates.io index
Downloaded memchr v2.5.0
Downloaded bitflags v1.3.2
Downloaded num-traits v0.2.15
Downloaded bstr v0.2.17
Downloaded pkg-config v0.3.26
Downloaded cc v1.0.79
Downloaded rlua v0.18.0
Downloaded autocfg v1.1.0
Downloaded libc v0.2.139
Downloaded 9 crates (1.8 MB) in 11.08s
Compiling rlua v0.18.0
error: failed to run custom build command for `rlua v0.18.0`
Caused by:
process didn't exit successfully: `/mnt/shared/target/debug/build/rlua-406b6ab30ac28d1e/build-script-build` (exit status: 101)
--- stderr
thread 'main' panicked at 'Cannot enable more than one Lua interpreter feature.', /usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/rlua-0.18.0/build.rs:21:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
ビルドに失敗しました。
別の動作しているプロジェクトを見たところ、Cargo.toml に default-features = false
が記述されていたので、指定してみたところ、ビルドができるようになりました。
rlua 0.19 の場合
現時点の rlua の最新版は 0.19.4 です。
0.19 系を使ってみます。
# cargo add --no-default-features --features system-lua53 rlua@0.19.0
# cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.11s
Running `target/debug/rluacjson`
Hello, world!
RuntimeError("[string \"?\"]:2: module 'cjson' not found:\n\tno field package.preload['cjson']\n\tno file '/usr/local/share/lua/5.3/cjson.lua'\n\tno file '/usr/local/share/lua/5.3/cjson/init.lua'\n\tno file '/usr/local/lib/lua/5.3/cjson.lua'\n\tno file '/usr/local/lib/lua/5.3/cjson/init.lua'\n\tno file '/usr/share/lua/5.3/cjson.lua'\n\tno file '/usr/share/lua/5.3/cjson/init.lua'\n\tno file './cjson.lua'\n\tno file './cjson/init.lua'\nstack traceback:\n\t[C]: in ?\n\t[C]: in function 'require'\n\t[string \"?\"]:2: in main chunk")
ビルドはできましたが、cjson を見つけられない、というようなエラーになりました。0.18 系でしか動かすことができませんでした...
Lua 5.4 の場合
現時点の Lua の最新版は 5.4.4 です。
5.4 系を使ってみます。
# apt update
# apt install -y lua5.4 liblua5.4-dev
# cd ~
# wget https://luarocks.org/releases/luarocks-3.9.2.tar.gz
# tar zxpf luarocks-3.9.2.tar.gz
# cd luarocks-3.9.2
# ./configure --with-lua-include=/usr/include/lua5.4
# make
# make install
5.3 系と同じ手順でセットアップを進めます。
# cargo add --no-default-features --features system-lua54 rlua@0.18.0
# cargo build
Downloaded bitflags v1.3.2
Downloaded rlua v0.18.0
Downloaded memchr v2.5.0
Downloaded bstr v0.2.17
Downloaded pkg-config v0.3.26
Downloaded num-traits v0.2.15
Downloaded autocfg v1.1.0
Downloaded libc v0.2.139
Downloaded 8 crates (1.7 MB) in 10.88s
Compiling rluacjson v0.1.0 (/mnt/shared)
error: linking with `cc` failed: exit status: 1
|
= note: "cc" "-m64" "/tmp/rustcsuQeZP/symbols.o" ...
: (中略)
= note: /usr/bin/ld: /mnt/shared/target/debug/deps/librlua-64dafec8882567bf.rlib(rlua-64dafec8882567bf.rlua.f15fbb14-cgu.10.rcgu.o): in function `rlua::lua::create_lua':
/usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/rlua-0.18.0/src/lua.rs:514: undefined reference to `lua_setcstacklimit'
collect2: error: ld returned 1 exit status
= help: some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
= note: use the `-l` flag to specify native libraries to link
= note: use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname)
error: could not compile `rluacjson` due to previous error
ビルドに失敗しました。undefined reference to ``lua_setcstacklimit'
と出力されていますが、解決できず...
おわりに
Lua 5.3 + rlua 0.18 で cjson を使用するコードを実行することができました。