作者:buxiu 轉自:Lua中文網站(www.luachina.net)
這次與第二篇文章相反,介紹如何在Lua中調用C/C++函數,首先,我們用C/C++創建一個函數並告訴Lua解釋器,然後在Lua中調用這個函數並使用函數的返回值。
定義一個C/C++函數:
要想C/C++中的函數能被Lua調用,函數定義必須這樣:
也就是說,函數必須以Lua解釋器作爲參數,並且返回值爲int類型。既然Lua解釋器作爲函數的參數,那麼實際上函數可以從棧中取得任意多個參數。下面我們將看到,返回的整數值代表入棧的值的數目。如果有一個C/C++函數,你想在Lua中調用他,很容易封裝一下就可以滿足上述要求。
下面的C++的average函數例子中,可以清楚地看到Lua中調用C/C++函數是如何實現的。
1. lua_gettop()返回棧頂的下標索引,由於Lua中棧的下標從1開始,這個返回值實際上也就是函數參數的個數。
2. For循環計算各個參數總和。
3. Average的參數是通過調用lua_pushnumber()入棧的。
4. 然後參數之和被入棧。
5. 最後,函數返回值爲2,表明有兩個返回值,並且已經入棧。
函數被定義之後,我們必須告訴Lua編譯器他的存在,這在main()函數中,在Lua解釋器被初始化,類庫加載之後完成的。
將下面的代碼保存爲luaavg.cpp,如果你喜歡用C而不是C++,需要保存文件爲luatest.c並且把extern去掉。
extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
/* the Lua interpreter */
lua_State* L;
static int average(lua_State *L)
{
/* get number of arguments */
int n = lua_gettop(L);
double sum = 0;
int i;
/* loop through each argument */
for (i = 1; i <= n; i++)
{
/* total the arguments */
sum += lua_tonumber(L, i);
}
/* push the average */
lua_pushnumber(L, sum / n);
/* push the sum */
lua_pushnumber(L, sum);
/* return the number of results */
return 2;
}
int main ( int argc, char *argv[] )
{
/* initialize Lua */
L = lua_open();
/* load Lua base libraries */
lua_baselibopen(L);
/* register our function */
lua_register(L, "average", average);
/* run the script */
lua_dofile(L, "avg.lua");
/* cleanup Lua */
lua_close(L);
return 0;
}
一個簡單的Lua腳本,調用C/C++函數,並打印其返回值,保存爲avg.lua:
avg, sum = average(10, 20, 30, 40, 50)
print("The average is ", avg)
print("The sum is ", sum)
編譯:
Linux平臺,鍵入命令:
運行程序:
如果正常的話程序應該顯示:"The sum is 25"
如果你不是Linux操作系統,使用的是Vc++編譯器,你需要:
1. 創建一個新的win32控制檯應用工程。
2. 將文件luaavg.cpp添加到你的工程中。
3. 到Project, Settings點擊Link頁。
4. 添加lua+lib.lib到Object/library modules列表中。
5. 按F7編譯程序。
運行程序以前,你需要確保lua+lib.dll文件放在windows可以找到的地方,將這個文件從C:/Program Files/Lua-5.0拷貝到Visual C++ project目錄,如果編譯沒有錯誤的話,現在可以Ctrl+F5運行程序了。
關於錯誤處理:
如果你看過Lua API文檔,你會發現在上面的average函數中並未進行參數檢查,這樣做的目的是爲了更容易解釋問題,但是在一個實際的程序中錯誤檢查是必要的。在上面的例子中我們至少應該確保每一個參數是一個整數,可以用下面代碼實現:
lua_pushstring(L, "Incorrect argument to 'average'");
lua_error(L);
}
這樣易於以後的調試。在使用兩種語言進行開發的時候這是非常重要的一點,否則你會發現你將陷於忙於兩種語言之間進行調試。