Lua
Lua C API入門
サーチ…
構文
- lua_State * L = lua_open(); //新しいVM状態を作成します。ルア5.0
- lua_State * L = luaL_newstate(); //新しいVM状態を作成します。 Lua 5.1+
- int luaL_dofile(lua_State * L、const char * filename ); //指定されたlua_Stateを使用して、指定されたファイル名で luaスクリプトを実行する
- void luaL_openlibs(lua_State * L); //すべての標準ライブラリを指定されたlua_Stateにロードする
- void lua_close(lua_State * L); // VMの状態を閉じ、内部のすべてのリソースを解放する
- void lua_call(lua_State * L、int nargs、int nresults); //インデックスのルアーブルを呼び出します。 - (nargs + 1)
備考
Luaは、仮想マシンに適切なC APIを提供します。 VM自体とは対照的に、C APIインタフェースはスタックベースです。したがって、データで使用されることが意図されている機能のほとんどは、仮想スタックの上にいくつかのものを追加するか、またはそこから削除することです。また、すべてのAPI呼び出しをスタック内で慎重に使用する必要があります。
一般に、Lua言語で利用可能なものはすべて、C APIを使用して実行できます。また、内部レジストリへの直接アクセス、標準メモリアロケータまたはガベージコレクタの動作変更などの追加機能もあります。
あなたの端末で以下を実行することによって、提供されたLua C APIの例をコンパイルすることができます:
$ gcc -Wall ./example.c -llua -ldl -lm
Lua仮想マシンの作成
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
int main(void)
{
/* Start by creating a new VM state */
lua_State *L = luaL_newstate();
/* Load standard Lua libraries: */
luaL_openlibs(L);
/* For older version of Lua use lua_open instead */
lua_State *L = lua_open();
/* Load standard libraries*/
luaopen_base(L);
luaopen_io(L);
luaopen_math(L);
luaopen_string(L);
luaopen_table(L);
/* do stuff with Lua VM. In this case just load and execute a file: */
luaL_dofile(L, "some_input_file.lua");
/* done? Close it then and exit. */
lua_close(L);
return EXIT_SUCCESS;
}
Lua関数を呼び出す
#include <stdlib.h>
#include <lauxlib.h>
#include <lua.h>
#include <lualib.h>
int main(void)
{
lua_State *lvm_hnd = lua_open();
luaL_openlibs(lvm_hnd);
/* Load a standard Lua function from global table: */
lua_getglobal(lvm_hnd, "print");
/* Push an argument onto Lua C API stack: */
lua_pushstring(lvm_hnd, "Hello C API!");
/* Call Lua function with 1 argument and 0 results: */
lua_call(lvm_hnd, 1, 0);
lua_close(lvm_hnd);
return EXIT_SUCCESS;
}
上記の例では、次のことを行っています。
- 最初の例に示すように、Lua VMの作成と設定
- グローバルLuaテーブルから仮想スタックにLua関数を取得してプッシュする
- 仮想スタックに入力引数として文字列
"Hello C API"
をプッシュする - VMが既にスタックにある1つの引数を持つ関数を呼び出すように指示する
- 閉鎖と清掃
注意:
念頭におくと、 lua_call()
は関数をポップし、スタックからの引数は結果だけを残します。
また、代わりにLuaで保護されたコールを使用する方が安全lua_pcall()
。
カスタムAPIとLuaのカスタマイズを含む組み込み型Luaインタプリタ
LuaインタプリタをCコードに埋め込み、Cで定義された関数をLuaスクリプトに公開し、Luaスクリプトを評価し、LuaからCで定義された関数を呼び出し、C(ホスト)からLuaで定義された関数を呼び出す方法を示します。
この例では、Luaスクリプトによって気分が設定されるようにします。ここはmood.luaです:
-- Get version information from host
major, minor, build = hostgetversion()
print( "The host version is ", major, minor, build)
print("The Lua interpreter version is ", _VERSION)
-- Define a function for host to call
function mood( b )
-- return a mood conditional on parameter
if (b and major > 0) then
return 'mood-happy'
elseif (major == 0) then
return 'mood-confused'
else
return 'mood-sad'
end
end
スクリプトでmood()
が呼び出されていないことに注意してください。これは、ホストアプリケーションが呼び出すために定義されたものです。また、スクリプトは、スクリプトで定義されていないhostgetversion()
という関数を呼び出します。
次に、mood.luaを使用するホストアプリケーションを定義します。ここに 'hostlua.c'があります:
#include <stdio.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
/*
* define a function that returns version information to lua scripts
*/
static int hostgetversion(lua_State *l)
{
/* Push the return values */
lua_pushnumber(l, 0);
lua_pushnumber(l, 99);
lua_pushnumber(l, 32);
/* Return the count of return values */
return 3;
}
int main (void)
{
lua_State *l = luaL_newstate();
luaL_openlibs(l);
/* register host API for script */
lua_register(l, "hostgetversion", hostgetversion);
/* load script */
luaL_dofile(l, "mood.lua");
/* call mood() provided by script */
lua_getglobal(l, "mood");
lua_pushboolean(l, 1);
lua_call(l, 1, 1);
/* print the mood */
printf("The mood is %s\n", lua_tostring(l, -1));
lua_pop(l, 1);
lua_close(l);
return 0;
}
出力は次のとおりです。
The host version is 0 99 32
Lua interpreter version is Lua 5.2
The mood is mood-confused
'hostlua.c'をコンパイルした後でも、私たちはプログラムの出力を変更するために 'mood.lua'を自由に変更することができます!
テーブル操作
テーブルのインデックスにアクセスしたり変更したりするには、テーブルをスタックに配置する必要があります。
この例では、テーブルがtblという名前のグローバル変数であると仮定しましょう。
特定のインデックスでコンテンツを取得する:
int getkey_index(lua_State *L)
{
lua_getglobal(L, "tbl"); // this put the table in the stack
lua_pushstring(L, "index"); // push the key to access
lua_gettable(L, -2); // retrieve the corresponding value; eg. tbl["index"]
return 1; // return value to caller
}
これまで見てきたように、テーブルをスタックにプッシュし、インデックスをプッシュしてlua_gettableを呼び出すだけです。 -2引数は、テーブルがスタックの先頭から2番目の要素であることを意味します。
lua_gettableはメタメソッドをトリガーします。メタメソッドをトリガしたくない場合は、代わりにlua_rawgetを使用してください。同じ引数を使用します。
特定のインデックスにコンテンツを設定する:
int setkey_index(lua_State *L)
{
// setup the stack
lua_getglobal(L, "tbl");
lua_pushstring(L, "index");
lua_pushstring(L, "value");
// finally assign the value to table; eg. tbl.index = "value"
lua_settable(L, -3);
return 0;
}
コンテンツを取得するのと同じドリル。スタックをプッシュし、インデックスを押してから、値をスタックにプッシュする必要があります。その後、lua_settableを呼び出します。 -3引数はスタック内のテーブルの位置です。メタメソッドの起動を避けるには、lua_settableの代わりにlua_rawsetを使用します。同じ引数を使用します。
テーブルから別のコンテンツへの転送:
int copy_tableindex(lua_State *L)
{
lua_getglobal(L, "tbl1"); // (tbl1)
lua_getglobal(L, "tbl2");// (tbl1)(tbl2)
lua_pushstring(L, "index1");// (tbl1)(tbl2)("index1")
lua_gettable(L, -3);// (tbl1)(tbl2)(tbl1.index1)
lua_pushstring(L, "index2");// (tbl1)(tbl2)(tbl1.index1)("index2")
lua_pushvalue(L, -2); // (tbl1)(tbl2)(tbl1.index1)("index2")(tbl1.index1)
lua_settable(L, -4);// (tbl1)(tbl2)(tbl1.index1)
lua_pop(L, 1);
return 0;
}
今ここで学んだことのすべてをまとめています。私はあなたが迷子にならないようにコメントにスタックの内容を入れます。
両方のテーブルをスタックに配置し、テーブル1のインデックスをスタックにプッシュし、 tbl1.index1
値を取得します。 gettableの-3
引数に注意してください。私は最初のテーブル(上から3番目)を見ていて、2番目のテーブルではありません。次に、2番目のテーブルのインデックスをプッシュし、 tbl1.index1
をスタックの先頭にコピーしてから、4番目の項目の上からlua_settable
を呼び出します。
家事酒のために、私は一番上の要素をパージしたので、2つのテーブルだけがスタックに残っています。