tolua++は便利なんですが、従来のlua_Stateを受け取る形ができません。
tolua++はC言語のグルーコードを生成してくれるツールなので、
C言語で書けない形式は生成できないのです。
ですから、可変長引数、可変長返り値、型がわからない引数などは受け取れません。
int foo(lua_State *); という関数だと、自動的に見切ってくれないかな~という淡い期待は打ち砕かれ…。
ちなみに、int foo(...); という形式なら、未対応と言われて終了です。
そこで何とかしたのがこれ。
class Test{
public:
int action1(lua_State *L);
int action2(lua_State *L);
};
template <typename T, int (T::*F)(lua_State *) >
int glue_func(lua_State *L){
T *self = (T *) tolua_tousertype(L,1,0);
lua_remove(L, 1);
int ret = (self->*F)(L);
return ret;
}
void regist(lua_State *L){
luaL_getmetatable(L, "Test");
lua_pushcfunction(L, (lua_CFunction)( glue_func<Test, &Test::action1>) );
lua_setfield(L, -2, "action1");
lua_pushcfunction(L, (lua_CFunction)( glue_func<Test, &Test::action2>) );
lua_setfield(L, -2, "action2");
lua_pop(L, 1);
}
まず、tolua++で、Testのクラスだけはグルーコードを生成しておきます。
action1, action2 はluaを使って登録するので、tolua++でグルーコードは生成しません。
登録する関数は、glue_funcのテンプレートを使って、自動的にグルーコードを作ってやります。
ここで偉い人から頂いた解答をコピペしただけですけど。
ただ、このコードはselfが本当にTest型なのか調べずにキャストしているので、よいコードではありません。
本来なら、tolua_isusertypeを使って、Test型なのかのチェックをするべきでしょう。
わざわざ、こんな方法を考えるきっかけは、Luaの関数型を受け取りたかったわけです。
関数型はC言語で表せないので、受け取ることはできません。
しかし、この関数型はとても便利ですので、使えないからと諦めるには惜しすぎます。
関数型をC言語で扱う方法は「[C][Lua]Luaの中の迷宮」を見てください。