二、C/C++函數調用LUA函數
爲應用程序註冊新的C函數到Lua是擴展Lua的基本方法之一。一般本說,從Lua中調用C函數,不是指Lua可以調用任何類型的C函數。對於一個C函數來說,要調用Lua函數就必須遵循一些簡單的協議來傳遞參數和獲取返回結果。與此類似,從Lua中調用C函數,也必須遵循一些協議來傳遞參數和獲得返回結果。具體來說,Lua和C上通過棧來交互的。特別注意的是,當Lua中調用C函數的時候,被調用的C函數總是獲得一個新的LUA棧,這個棧不同於一般的棧以及C函數自己的棧。它包含最初的所有要傳遞給C函數的參數,也作爲C函數將執行結果返回給調用者(LUA)的地方,即C函數push執行結果到棧上。爲了方便,對這個棧的許多查詢操作並不遵循嚴格的棧操作,相反,可以通過索引來訪問棧上的任意元素。棧中的每個數據通過索引值進行定位,索引值爲正時表示相對於棧底的偏移索引,索引值爲負時表示相對於棧頂的偏移索引,索引值以1或-1爲起始值,因此棧頂索引值永遠爲-1 ,棧底索引值永遠爲1 。
C函數調用Lua函數必須遵循的協議:首先,把被調用的LUA函數(地址)push到棧上;然後,將函數所需的所有參數按從左到右的順序push到棧上,也就是說,第一個參數首先被push到棧;最後一步是調用lua_call(或者lua_pcall)。當LUA函數被調用,棧上所有的參數和函數地址都被從棧上彈出。
下面是一個C函數調用Lua函數的例子:
testluafunc.cpp的內容如下:
// …omitted…
lua_getglobal(L, "MyLuaAdd"); // push MyLuaAdd-fuction
lua_pushnumber(L, 10); // push first-argument
lua_pushnumber(L, 11); // push second-argument
lua_pcall(L, 2, 1, 0); // call MyLuaAdd-fuction
std::cout << "myadd(10, 11) == "
<< lua_tonumber(L, -1) // query result
<< std::endl;
lua_pop(L,1); // discard result from stack
// …omitted…
C函數調用Lua函數(全局變量)的過程:
(1) 將Lua函數(全局變量)入棧(eg. lua_getglobal(L, "MyLuaAdd"))
(2) 對於全局變量,直接通過lua_toXXX等函數直接從棧取出數據即可。而對於調用Lua函數,則按從左到右的順序將各參數入棧。
(3) 指明參數個數以及返回值(以及錯誤處理),由lua_pcall或其它函數來調用LUA函數。
(4) 通過lua_toXXX等函數直接從棧取出LUA函數執行的結果即可。