LoginSignup
0
0

rluaを利用する 2024

Last updated at Posted at 2024-02-20

情報が少なめ

自由度の高いコンフィギュレーションを可能にするだとか、独自のファンタジーコンソールで張り合うとかもろもろ考えられると思いますが、コンパイルしないと結果を変更できないのは小回りも利かず不便なこともありますね? rluaで自由を手に入れましょう。

対象 version

rlua 0.20.0
rustc 1.75.0

基本の基本

Cargo add rlua でCrateを追加。

use rlua::Lua;

fn main() {

    // rluaの初期化
    let lua = Lua::new();
    
    // luaとrustのやり取りをするインターフェイス的なものを取得
    let globals = lua.globals();

    // lua側に値を渡す
    globals.set("name", "Taro").unwrap();

    // luaスクリプトの実行をする。
    lua.load(r#"
        print("Hello, "..name);
        ans = 123;
    "#).exec().unwrap();

    // lua側の変数から値を取得して表示
    let ans: i32 = globals.get("ans").unwrap();
    println!("{}", ans);
}

簡単なやり取りはこのような感じ。
これでRustとlua間で値のやり取りとかが出来ます。

Rust側からluaに値を渡すときはあまり意識しなくても大丈夫なのですが、luaからRustに値を取り出す際には型指定が必須ですので注意が必要です。

Stringやi32などなどの変数でやり取りも良いのですがHashMapとTableのやりとりが抜群に便利なのでポイントかと思います。

use std::collections::HashMap;

let mut my_hashmap: HashMap<&str, &str> = HashMap::new();
my_hashmap.insert("Country", "Japan");
my_hashmap.insert("City", "Tokyo");
globals.set("my_table", my_hashmap).unwrap();

このようにRust側から値を送り込んで以下のようにlua側で利用が可能です。

print(my_table["Country"].." / "..my_table["City"]);

luaから呼べるRustの関数をつくる

こんな風にしてluaから呼べる関数を作ることができます。

let hello_func = lua.create_function(|_, _:()| {
  println!("Hello!");
  Ok(())
}).unwrap();
globals.set("hello", hello_func).unwrap();

luaから関数を呼ぶことが出来るようになっているのを確認します。

hello();

create_functionは無名関数として定義します。
引数がない場合はこうですが、引数がある場合は、例えば(i32, String)だった場合は(|_, (index, text): (i32, String)| { }のように定義します。
何にしても無名関数なので困ったことがあったら「Rust 無名関数」などと探せばヒントがあるはず。

日本語で困る

lua側で日本語を表示すると文字化けしたりします。
テーブルのキー名、値に日本語データ(もちろんUTF8限定)を使うことは可能だし、文字列操作した変数をRust側で引き出して利用するのは全く問題ないのでlua側で日本語を表示したいなどの要求がある場合は注意。

※2024/02/27追記
わたしが文字化けに悩まされていたのはWindowsのPowerShell環境。
コントロールパネル>地域>管理>システムロケールの変更 から
「ベータ:ワールドワイド言語サポートでUnicode UTF-8を使用」にチェックし、Windowsの再起動後PowerShell上でLua側の表示を文字化けせず表示させることが出来ました。

lua側で定義していない変数をRust側で引いた場合

エラーです。
でもそれだと困るので、次のようにしてエラーハンドリングを行います。
※普通のRustのエラーハンドリングです。

let my_value: Result<String, rlua::Error> = globals.get("value");
match my_value {
    Ok(v) => println!("{}", v),
    Err(e) => println!("Error: {}", e),
}

このように受けとることでlua側にない変数を引いた際、或いは別の問題があった場合にエラー処理が可能となります。

最後に、本当に簡単にrluaの現在の使い方について触れてみましたが、本当に本当に簡単にしか触れておらず不足もあるかと思いますが何かしらの足がかりになればと思います。

個人的にはデータ変換ツールのコンフィギュレーションにluaが使えれば便利だろうなと思い調べたところネット上でのrluaの解説が古いことに気づいてこれを書くに至りました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0