軽量言語の部屋。Lua + C(++)が多めかもしれない。
ダウンロードはこちら ⇒ lua03.zip
息抜きにluaだけ。説明はソース。
a length= 10
取り出すときも以下の通り
a[1]=test1
a[2]=test2
a[3]=test3
a[4]=test4
a[5]=test5
a[6]=test6
a[7]=test7
a[8]=test8
a[9]=test9
a[10]=test10
b length= 0
key valueは長さが取れないのである。よくハマる
test_key1
test_key1
key5 test_key5
key6 test_key6
key9 test_key9
key2 test_key2
key4 test_key4
key10 test_key10
key1 test_key1
key8 test_key8
key3 test_key3
key7 test_key7
ダウンロードはこちら ⇒ lua02.zip
C側の全コードはこちら。
#include <stdio.h>
#include <lua/lua.hpp>
int main() {
lua_State *L = luaL_newstate();
luaL_openlibs(L);
if(luaL_dofile(L, "test.lua")) {
printf("%s\n", lua_tostring(L, -1));
return -1;
}
//test.luaで定義された大域Helloをスタックに積む
lua_getglobal(L, "Hello");
lua_getglobal(L, "World");
printf("%s\n", lua_tostring(L, -1)); //積まれたWorldを文字列で出力
printf("%s\n", lua_tostring(L, -2)); //積まれたHelloを文字列で出力
//スタックをpop(WorldとHelloが詰まってるスタックを破棄する)
lua_pop(L, 2);
printf("lua_gettop(L)=%d\n", lua_gettop(L));
lua_close(L);
return 0;
}
実行結果がトップの写真の通り。
lua_tostringで指定している引数は、tostringするstackのindexです。
lua_getglobalでスタックに取ってきた値を積んで、lua_tostringで変換します。
変換するスタックの対象をindexで指定します。
積んだスタックのトップは-1に詰まってます。
実行結果が、
Konnichiha
Sekai
じゃなくて、
Sekai
Konnichiha
になってるのは、Worldがスタックが最後に積まれたから。LIFOですね。
lua_popでスタックを何個捨てるか(実際はマクロになってて、実態はlua_settop)指定して、必要に応じてきれいにして終わり。
さて、面倒ですね。
LuaBindとかいう先駆的なバインダがあるんですが、まあ車輪の再発明というほどでもないので、
これをうまい事C++にバインドする方法を考えてみましょう(うまくいくかな...)
サンプル : lua00.zip
まず、Luaの文法、Tutorialを読む!ってところが王道だと思うんですが、超簡単なLuaはこれ。
Hello = "Konnichiha, "
World = "Sekai"
print(Hello .. World)
wandboxなどで確認してみるといいだろう。
よくある構文 + ..で文字列連結。簡単だ。
よく;が末尾に無いと使えない!って人もいると思いますが、まあ慣れです慣れ。;あっても別にいいです。
うっかりほかの言語に戻ったときにコンパイルミスやらかすくらいです。ハハハ。
本題。こいつをCから読み込ませたい。
C側ではlua_State(lua.hpp)というLuaの環境保持するコンテキストを生成する。あらゆるLuaの操作はそのコンテキストを渡して操作する。
サンプルは以下。
#include <stdio.h>
#include <lua/lua.hpp>
int main() {
//Luaの新しい環境を生成
lua_State *L = luaL_newstate();
//Luaの標準ライブラリ読み込み
luaL_openlibs(L);
//test.luaをファイルとして読み込んで実行。
//実行されるとLに一通り実行された状態が記録される。
if(luaL_dofile(L, "test.lua")) {
printf("%s\n", lua_tostring(L, -1));
}
//test.luaにあるHelloというグローバル変数をスタックにロードして文字列で表示
lua_getglobal(L, "Hello");
printf("%s\n", lua_tostring(L, -1));
//test.luaにあるWorldというグローバル変数をスタックにロードして文字列で表示
lua_getglobal(L, "World");
printf("%s\n", lua_tostring(L, -1));
//文字列を直接Luaスクリプトとして実行
luaL_dostring(L, "print('LUA! LUA!')");
//Luaの環境を削除
lua_close(L);
return 0;
}
説明の通り。シンプル。
test.luaで定義したグローバル変数もC側で読めてしまう。
ただluaスクリプト読み込ませるだけなら以下。
#include <stdio.h>
#include <lua/lua.hpp>
int main() {
lua_State *L = luaL_newstate();
luaL_openlibs(L);
if(luaL_dofile(L, "test.lua")) {
printf("%s\n", lua_tostring(L, -1));
}
lua_close(L);
return 0;
}
あれっ簡単じゃね?
さて、スタックって出てきましたがそれは次以降。
はぁ~~~~~???今更Luaァ!?って思ったそこのキミ!いいぞぉLuaは。
なんかIntrinsic Alchemyって統合開発環境でLuaを初めて知った気がする。もう15年位前か~。
まともに使い始めたのは2010年ころからだけど(もっと前かもしれない)いまだにそこらのルーターだったり機材の中でしぶとく生きている。
例えばYAMAHAのルーターのスクリプティングにLuaが採用されている。
(YAMAHA)Lua スクリプト機能
Oh!すごいネ!MMORPGのAI組むのに使用されていたり、CRYENGINEでのスクリプティングに採用されていたり、
ちゃんと使われてるんだ。
そして、特に改造しないと近年のマルチコア事情に全然ついていけてない(必要性などいろいろ議論がある)
文法が古くて困る!割と雑に使える!スタックベースで素朴すぎる!
というところが良いのである。
あとよっぽどのへぼコンパイラじゃなければ適当なクロスコンパイラ, VC201Xでさっさとコンパイルできて、さっさと使える。
余計なことをしないクールなやつだ。ビューリフォー。
Windowsひいきで解説する。
Windowsだとプロジェクト開いて誰かが作ったのか分からないソリューションを開いてコンパイルする、
もしくは自分でプロジェクトまで作っちゃうってのもアリですが、コマンドラインからobj作るまでなら以下で一発だ。
※wgetから書く。あとclのオプションは/c以外は趣味。
wget https://www.lua.org/ftp/lua-5.3.4.tar.gz
tar xvf lua-5.3.4.tar.gz
cd lua-5.3.4/src/
cl *.c /Ox /EHsc /GS- /c
超簡単。lua.objとluac.objをrmしたらlib(arでもいい)コマンドで固めたらlua.lib(a)が出来上がる。
楽勝だね。ちなみにコマンドはこちら。
mkdir temp
move lua.obj luac.obj temp
lib *.obj /out:lua.lib
move temp/* .
makefileがあるからXXnux環境系なら一撃だ。
lib + lua.objでlua、lib + luac.objでluacが出来上がる。なんて強いんだ。
後は近年のluaは、ちゃあんとlua.hppがあって、extern "C"書かなくてもいいのである。
次あたりから解説するCとの連携周りでつかいまっする。
なんかかなり昔のlua、いちいち自分でlua.hppを書いてた気がするネー
そもそもLuaいつ頃知ったんだろう。謎。
おわりである。