tolua++その4(hook関数)

http://www.codenix.com/~tolua/tolua++.html#customizing

toluaコマンドの"-L"オプションでhook関数を上書きできる(元は、basic.luaに空の関数が書いてある)。

doit.lua:doit()
↓
package.lua:Package()
  ↓
  preprocess_hook(p)
  ↓
  p:preprocess()
  ↓
  preparse_hook(p)
  ↓
  p:parse()
    ↓
    parser_hook(s)#########################################################
# パッケージのパースが終わり
#########################################################
↓
pre_output_hook(p)
↓
p:preamble()
p:supcode()
↓
pre_register_hook(p)
↓
p:register()
↓
post_output_hook(p)

他のは細かすぎてわからなかったので放置した。
パッケージファイルをパース後、クラスに関数を追加したいときなんかはpre_output_hookを使えばよいと思う。
たとえば、こんなwindow.pkgを作って

$#include "window.h"

namespace win32 {

  class Window
  {
    void draw();
    void show(bool isShow);
    void move(int x, int y);
    void resize(int w, int h);
  };

}

こいつに

int setMouseLeftPressCallback(lua_State *L);

というlua関数を引数に取れるメソッドを足してやりたい時に、hook関数で後付けで追加することができる。
hook関数上書きようのluaスクリプトを用意。hook.lua

-- packageツリーをたどって名前の一致するものを探す
local function find(p, name)
    if p.name==name then
        return p
    end

    for i, v in ipairs(p) do
        if type(v)=='table' then
            local found=find(v, name)
            if found then
                return found
            end
        end
    end
    return nil, '"'..name..'" not found'
end

-- 対象のパッケージに関数を追加する
local function appendTo(p, target, f)
    local t=assert(find(p, target))
    if t then
        print("found: ", target, t)
        setmetatable(f, { __index=classFunction})
        table.insert(t, f)
    end
end

-- hook関数上書き
function pre_output_hook(p)
    appendTo(p, "win32::Window", {
      lname="setMouseLeftPressCallback", 
      -- いったんstaticまたは通常のc関数でthisポインタを取得する必要がある
      cname="win32::Window::setMouseLeftPressCallback",
    })
    p:print()
end

こんなんでパッケージの任意の場所にCの任意の関数またはstaticクラス関数を追加できる。

# -Lオプション
$ tolua -L hook.lua window.pkg
typedef int (*lua_CFunction) (lua_State *L);

型のものを特別扱いする方法がわからないので無理やりやっているのでこうなっている。
特別扱いする方法はありそうなのだが・・・


ちょうど去年やっていたところをまたやっているw
http://d.hatena.ne.jp/ousttrue/20100225/1267071607