2012-07-26 55 views
3

假設我們有許多具有相同簽名的C函數,我們希望將它們註冊到Lua。例如,每個函數看起來像這樣的:在Lua中註冊相同簽名的C函數

int wrap_foo(Lua_State *l) 
{ 
    int x = lua_tonumber(l, 1); 
    foo(x); 
    return 0; 
} 

lua_pushcfunction(l, wrap_foo); 
lua_setglobal(l, "foo"); 

的問題是:

void foo(int n) 
{ 
    // do some work 
} 

我們可以與他們每個人的登記如何實現以下功能,避免重複的代碼。

void register(Lua_State *l, const char *name, void (*f)(int)); 

可能的話,可以使用預處理器宏(僅限編譯時)執行此操作。有沒有更優雅的方式?我更喜歡沒有任何外部綁定庫的解決方案。

+2

你可能只是一個包裝函數,然後在每次註冊時在[upvalue](http://www.lua.org/pil/27.3.3.html)中存儲正確的函數指針。然後在函數中,只讀取upvalue並調用它。 – 2012-07-26 12:51:48

回答

2

你無法說出它register,因爲這是一個關鍵字,但如果我們把它稱爲,比方說,register_wrapper,我們可以實現詹姆斯·麥克勞克林的建議是這樣的:

// wrapper for a C function taking a single number argument 
// the C function is bound to this wrapper as an upvalue 
int wrapper(lua_State *L) 
{ 
    int x = lua_tonumber(L,1); 
    void (*wrapped)(int) = (void (*)(int)) lua_touserdata(L, lua_upvalueindex(1)); 
    wrapped(x); 
    return 0; 
} 

// bind a C function to our wrapper function 
void register_wrapper(lua_State* L, const char* name, void(*wrapped)(int)) 
{ 
    lua_pushlightuserdata(L, wrapped); 
    lua_pushcclosure(L, wrapper, 1); 
    lua_setglobal(L, name); 
} 

int main() 
{ 
    lua_State *L = luaL_newstate(); 
    register_wrapper(L, "foo", foo); 
    register_wrapper(L, "bar", bar); 
    ...