我們在上一篇學習了如何使用C++調用Lua,這一次我們處理相反的過程,使用Lua調用C++,我們使用Lua文章中一個average函數。
如何在Xcode中設定Lua環境請看:http://blog.csdn.net/honey199396/article/details/50900277
在這篇文章中我們将在C++中建立函數,告訴Lua解析器他的情況,最後從Lua調用它。後面我們也談一談lua程式的錯誤檢測。
定義函數
所有在Lua中被調用的C/C++函數都必須使用一下的定義方式:
typedef int (*lua_CFunction) (lua_State *L);
換句話說,函數必須要以Lua解析器作為參數并傳回一個int型變量。由于使用Lua解析器作為參數,是以函數實際上能夠從棧中取得任意數量的參數。
下面給出的C++函數average() 示範了如何接受多個參數并傳回超過一個值。該函數是一個與上面typedef相比對的函數。
- lua_gettop函數傳回棧頂的索引值。因為在Lua中棧是從1開始編号的,是以該函數獲得的值就是參數的個數。
- 在for循環中計算所有參數之和。
- 調用lua_pushnumber()将參數的平均值壓棧。
- 将參數之和壓入棧中。
- 最後,函數傳回2,說明有兩個傳回值在棧中。
現在函數定義好了,我們必須告訴Lua解釋器,這将在main函數中初始化Lua解釋器和載入庫後執行。
-- 注冊我們的函數
lua_register(L, "average", average);
将檔案儲存為luaavg.cpp ,如果你使用C代替C++,檔案名字命名為luaavg.c 并且去掉 extern “C”
#include <stdio.h>
extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
/* 指向lua解釋器的指針 */
lua_State* L;
static int average(lua_State *L)
{
/* 得到參數的個數 */
int n = lua_gettop(L);
double sum = ;
int i;
/* 循環周遊參數 */
for (i = ; i <= n; i++)
{
/* 所有參數求和 */
sum += lua_tonumber(L, i);
}
/* 壓入平均值 */
lua_pushnumber(L, sum / n);
/* 壓入和 */
lua_pushnumber(L, sum);
/* 傳回傳回值的個數 */
return ;
}
int main ( int argc, char *argv[] )
{
/* 初始化Lua */
L = luaL_newstate();
/* 載入Lua基本庫 */
luaL_openlibs(L);
/* 注冊自定義函數 */
lua_register(L, "average", average);
/* 執行avg.lua檔案 */
luaL_dofile(L, "avg.lua");
/* 關閉Lua */
lua_close(L);
/* 暫停 */
printf( "Press enter to exit..." );
getchar();
return ;
}
以下是調用average函數,傳入5個參數,并傳回兩個傳回值的lua檔案,我們儲存為avg.lua。
編譯
如果你的環境有什麼問題,繼續看上一篇文章。
Xcode command+r,輸出結果:
The average is
The sum is
Press enter to exit...
錯誤處理
如果你讀過LuaApi文檔,你會發現在我的average函數中沒有錯誤檢查的代碼,這樣做是為了友善說明,但是在項目中,你或許想有錯誤測試。在上面的例子中,我們至少應該檢查每個參數是不是數字。通過在for循環中添加下面的代碼來實作:
if (!lua_isnumber(L, i)) {
lua_pushstring(L, "Incorrect argument to 'average'");
lua_error(L);
}
添加這樣的檢查很容易,同時這樣也讓調試更容易。當處理用兩種不同語言編寫的程式的時候,這顯得相當重要。
本文翻譯自:http://gamedevgeek.com/tutorials/calling-c-functions-from-lua/,一部分是根據我自己的電腦環境寫的。