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で判定しつつ投げていけば、登録は自動でできる。けどやっぱりラッパー関数作るのめんどい。。。
そういえばコルーチン試してないな。。。それはまたの機会に。。。