LoginSignup
2
5

More than 5 years have passed since last update.

NLuaを使ってみる

Posted at

LuaインタプリタのC#ラッパーであるNLuaを試してみる。

NLuaはVisual StudioからだとNuGetで参照に追加できる。
ただしバージョンが古い。14年あたりで止まってる。
バージョンは5.2あたり。

簡単に使ってみる

テストコード
using (NLua.Lua instance = new NLua.Lua())
{
    instance.DoString("print 'hello'");

    instance["a"] = 12.34;

    instance.DoString("print(a)");

    instance.DoString("b = 2^5");
    instance.DoString("c = math.sin(45 / 180 * math.pi)");
    instance.DoString("d = 'abc'");

    Console.WriteLine(instance["b"] + " " + instance["b"].GetType());
    Console.WriteLine(instance["c"] + " " + instance["c"].GetType());
    Console.WriteLine(instance["d"] + " " + instance["d"].GetType());

    double b = instance.GetNumber("b");
    Console.WriteLine(b);
}
結果
hello
12.34
32 System.Double
0.707106781186547 System.Double
abc System.String
32

DoStringを使えば文字列でスクリプトを渡せる。
ファイルから実行したい場合はDoFileを使う。

インデクサーを使えばグローバル変数にアクセスできる。
ただしインデクサーの戻り値はobjectになる。
戻り値の型がわかっているならGetNumberのような、関数経由で取り出したほうがいい。

以降のサンプルではインスタンスの確保は省略。

テーブル

配列

テストコード
instance.DoString("table = { 1, 3, 5, 7 }");

NLua.LuaTable table = instance.GetTable("table");

foreach (double key in table.Keys)
{
    Console.WriteLine(key + " " + table[key]);
}
結果
1 1
2 3
3 5
4 7

特に変な挙動はない。keyがdoubleなのと1オリジンを除けば。

連想配

テストコード
instance.DoString("table = { a = 1, b = 'abc', c = 'def' }");

NLua.LuaTable table = instance.GetTable("table");

foreach (string key in table.Keys)
{
    Console.WriteLine(key + " " + table[key]);
}
結果
a 1
b abc
c def

順番は不定(実行するたびに変わる)。

備考

配列のkeyはdouble、連想配列のkeyはstringで与えられる。
配列にstringを指定した場合、連想配列にdoubleを指定した場合はInvalidCastExceptionが発生する。

LuaTable.Keysを一旦読み出した後に型をチェックすれば、配列か連想配列かを判定できる。

テストコード

object[] keys = new object[table.Keys.Count];
table.Keys.CopyTo(keys, 0);

Console.WriteLine(keys[0].GetType() == typeof(string) ? "連想配列です" : "配列です");

LuaからC#の関数を呼び出す

クラス
class Hoge
{
    double i;

    public Hoge(double i)
    {
        this.i = i;
    }

    public double mul(double j)
    {
        return (i * j);
    }
}
テストコード
Hoge hoge1 = new Hoge(2);
Hoge hoge2 = new Hoge(10);

instance.RegisterFunction("mul1", hoge1, typeof(Hoge).GetMethod("mul"));
instance.RegisterFunction("mul2", hoge2, typeof(Hoge).GetMethod("mul"));

instance.DoString("print(mul1(5))");
instance.DoString("print(mul2(5))");
結果
10
50

複数のインスタンスのメソッドを呼び分けられる。

C#からLuaの関数を呼び出す(ついでに登録も)

テストコード
instance.DoString("function func(a, b) print(a) print(b) end");
instance.DoString("func(123, 'abc')");
結果
123
abc

DoStringでfunction hoge() ... endを与えれば関数として登録される。
DoStringで関数呼び出しもできる。

C#からLuaの関数を呼び出す(そして戻り値を受け取る)

テストコード
instance.DoString("function func() return({ a = 123, b = 'abc' }) end");
NLua.LuaTable table = (NLua.LuaTable)instance.DoString("return(func())")[0];

foreach (string key in table.Keys)
{
    Console.WriteLine(key + " " + table[key]);
}
結果
a 123
b abc

関数呼び出しとテーブルの取り出しの合わせ技。

DoStringで関数を呼び出しただけでは何も返してくれない。
returnで関数からの戻り値を返す必要がある。

ほげ

他にもモジュールとかいろいろな機能があるけど、とりあえず上記のあたりを使えばC#のプログラムに簡単なスクリプト機能を追加できる。
C#のプログラムにスクリプトを追加したいだけならC#でいいんじゃ?

正直LuaにC#のメソッドを登録するregisterをやるのがめんどい。
Luaに登録する関数は適当な接頭辞つけて、GetMethodsをforeachで回してNameで判定しつつ投げていけば、登録は自動でできる。けどやっぱりラッパー関数作るのめんどい。。。

そういえばコルーチン試してないな。。。それはまたの機会に。。。

2
5
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
2
5