在上一篇文章(C調用lua函數)中,講述了如何用c語言調用lua函數,通常,A語言能調用B語言,反過來也是成立的。正如Java與c語言之間使用JNI來互調,Lua與C也可以互調。
當lua調用c函數時,使用了和c調用lua中的同一種棧,c函數從棧中得到函數,然後將結果壓入棧中。為了區分返回結果和棧中的其他值,每一個函數返回結果的個數。
這裡有個重要的概念:這個棧不是全域的結構,每個函數都有自己的私人局部棧。哪怕c函數調用了lua代碼,lua代碼再次調用該c函數,他們有各自獨立的局部棧。第一個參數的索引是1。
作為第一個例子,讓我們看看如何?一個簡單的函數,返回給定2個參數的和:
複製代碼 代碼如下:
static int l_plus(lua_State* L)
{
lua_Integer a = lua_tointeger(L, 1);
lua_Integer b = lua_tointeger(L, 2);
lua_pushinteger(L, a+b);
return 1;
}
每一個Lua註冊的函數都必須是這個原型,它已經在lua.h中定義了:
複製代碼 代碼如下:
typedef int (*lua_CFunction) (lua_State *L);
由於c函數返回了一個int類型的傳回值個數。因此,當壓入傳回值之前,不必要清理棧,lua會自動移除傳回值下面的任何資料。
在lua中使用該函數之前,我們需要註冊它。使用lua_pushcfunction,它接受一個c函數,然後在lua內部建立一個函數類型的值來表示該函數。
複製代碼 代碼如下:
lua_pushcfunction(L, lua_plus);
lua_setglobal(L, "myplus");
一個專業點的寫法是,我們必須檢查它的參數類型:
複製代碼 代碼如下:
static int l_plus(lua_State* L)
{
lua_Integer a = luaL_checkinteger(L, 1);
lua_Integer b = luaL_checkinteger(L, 2);
lua_pushinteger(L, a+b);
return 1;
}
完整代碼:
複製代碼 代碼如下:
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
static int l_plus(lua_State* L)
{
lua_Integer a = luaL_checkinteger(L, 1);
lua_Integer b = luaL_checkinteger(L, 2);
lua_pushinteger(L, a+b);
return 1;
}
int main()
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
lua_pushcfunction(L, l_plus);
lua_setglobal(L, "myplus");
if (luaL_dostring(L, "print(myplus(2,2))")) {
lua_close(L);
error("Failed to invoke");
}
lua_close(L);
return 0;
}
(完)