tolua++が生成したグルーコードを見てみる

 以前(http://d.hatena.ne.jp/kitfactory/20100511/1273583585)に作った、tolua++が生成したCとLuaの連携を実現するグルーコード。

LuaC言語との連携で大事なのは、Lua側にCの関数や型を登録してCとの関係を作り上げることと、実際の関数呼び出しの処理(Luaで関数が呼ばれたら、関係づいているCの関数に引数を渡して処理させ、その返値をLuaに戻す)だと思う。グルーコードはどうやって実現しているのだろうか。ちょっくら見てみよう。

 以前の例ではrequire文でDLLがロードされるときはrequire("cfunc")とした。これはcfuncというDLLのtolua_cfunc_open関数を呼ぶことを意味する。そこで、tolua_cfunc_open()の中身を見ると、型を登録したり、関数を登録したりという関数が見える。でもhello()関数を直接登録しているのではなく、hello()関数をラップしているtolua_cfunc_hello00()関数をhelloという名前で登録している。Luaでhello()だと思って呼び出しているのは、実はtolua_cfunc_hello00()関数ということか。



 で、hello()をラップしているtolua_cfunc_hello00()関数ではLuaの中でhello()を呼び出した時の引数をLuaVMが持っているスタックから引数を取り出して(スタックから数を取り出す tolua_tonumber)、実際のhello()関数を呼び出し、その返り値をLuaのスタックへ積んでいる。(tolua_pushnumber)



なるほど、よく出来てるなぁ。


/*
** Lua binding: cfunc
** Generated automatically by tolua++-1.0.92 on 05/11/10 21:34:46.
*/

#ifndef __cplusplus
#include "stdlib.h"
#endif
#include "string.h"

#include "tolua++.h"
#include "cfunc.h"

/* Exported function */
TOLUA_API int  tolua_cfunc_open (lua_State* tolua_S);


/* function to register type */
static void tolua_reg_types (lua_State* tolua_S)
{
}

/* function: hello */
#ifndef TOLUA_DISABLE_tolua_cfunc_hello00
static int tolua_cfunc_hello00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
 tolua_Error tolua_err;
 if (
     !tolua_isnumber(tolua_S,1,0,&tolua_err) ||
     !tolua_isnoobj(tolua_S,2,&tolua_err)
 )
  goto tolua_lerror;
 else
#endif
 {
  int i = ((int)  tolua_tonumber(tolua_S,1,0));
  {
   int tolua_ret = (int)  hello(i);
   tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
  }
 }
 return 1;
#ifndef TOLUA_RELEASE
 tolua_lerror:
 tolua_error(tolua_S,"#ferror in function 'hello'.",&tolua_err);
 return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE

/* Open function */
TOLUA_API int tolua_cfunc_open (lua_State* tolua_S)
{
 tolua_open(tolua_S);
 tolua_reg_types(tolua_S);
 tolua_module(tolua_S,NULL,0);
 tolua_beginmodule(tolua_S,NULL);
  tolua_function(tolua_S,"hello",tolua_cfunc_hello00);
 tolua_endmodule(tolua_S);
 return 1;
}


#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501
 TOLUA_API int luaopen_cfunc (lua_State* tolua_S) {
 return tolua_cfunc_open(tolua_S);
};
#endif