2016-07-02 119 views
2

一個簡單的生成示例。Lua從參數中獲取函數

protocol.onConnect(function() end, function() end, ...) 

現在在c中,我想要得到在參數#1,#2中的函數。
在字符串,數字......我們可以使用它們(lua_getstring,..),但我至少沒有找到如何獲得函數。

int luaProtocolOnConnect(lua_State* L) 
{ 
    int base_func // funC#1 
    int call_func // funC#2 
    .... 
} 

回答

3

你不能真正「獲得」一個Lua函數。 Lua函數,如Lua表,是純粹的Lua對象。因此,他們沒有C或C++模擬器。如果你想調用一個Lua函數,那是通過lua_call,lua_pcall或類似的函數完成的。這是在Lua棧上原位完成的。

所以你不能把一個Lua函數變成一個C++值。 可以做什麼是採取一個Lua函數和操縱它的各種方式,所有的Lua對象可以被操縱。

例如,假設您想要將一個Lua函數存儲在一個C++對象中,然後再調用其中存儲的Lua函數。顯然,你不能直接將Lua函數轉換爲C++值。 可以做的是將Lua函數存放在C++可以訪問的地方。你使用有一個C++類似的值來存儲Lua函數。對於您想要存儲的每個對象,此值必須是唯一的。存儲對象時獲得的值將保存在C++對象中。當需要檢索Lua函數時,只需使用存儲的值來檢索它。

因爲這是一個非常普遍的操作,Lua有方法來促進這一點。首先是Lua註冊表,一個C++可以訪問的表格,但Lua代碼不能(除非您授予它訪問權限)。

第二個是luaL_ref系列功能。 luaL_ref將堆棧頂部的任何內容都粘貼到您提供的表格中,並返回給您一個整數鍵,以便稍後使用它來檢索它。 lua_rawgeti可用於通過密鑰從表中檢索函數,luaL_unref接受表和整數鍵,當您完成該操作時,從表中刪除引用的函數。

所以,如果你想存儲這樣的功能,你只需要創建一個這樣的表,將其粘貼在註冊表中的一個已知位置(以便您可以隨時獲取它),然後使用luaL_ref來存儲這些功能。當它們打電話給他們時,用lua_rawgeti檢索它們。當你完成使用它們時,用luaL_unref銷燬它們。

3

您可以使用lua_isfunction來檢查它是否是一個函數,使用​​推動在堆棧的頂部的值,然後使用luaL_refluaL_ref(L,LUA_REGISTRYINDEX);),把它變成一個獨特的密鑰可以在以後參考檢索值(lua_rawgeti(L,LUA_REGISTRYINDEX,ref))並調用該函數。

+0

將事情直接引用到註冊表中可能不是一個好主意。除非您的代碼是將在該Lua環境中執行的唯一C/C++代碼。 –

+0

我一般同意,但在這種情況下,關鍵是保證是唯一的,我見過一些圖書館沒有問題(例如,winapi)。 OP可根據需要替換他們自己的表格。 –

+0

它只保證是唯一的「只要你不手動添加整數鍵到表't'」。 –