在Lua中調用C++函數

來源:互聯網
上載者:User

翻譯自http://gamedevgeek.com/tutorials/calling-c-functions-from-lua/

在Lua中調用C++函數

我的第二部分教程講解了怎樣在C++中調用Lua函數。在這部分中,我們將討論相反的情況——在Lua中調用C++函數。由於我沒有想到一個簡單的例子來說明這種情況,因此,我借用了Lua官方文檔中的average函數來進行講解。

本教程涵蓋了Lua5.1。在Lua的每一個版本中都有一些非常不同之處。下面的範例程式碼將不能在老版本的Lua下運行。如果你仍然在使用老版本而且不願意升級,不用擔心,我已經在文章底部提供了4.0和5.0教程的原始碼下載串連。好了,讓我們開始吧!

在本文中我們將用C++建立一個函數,告訴Lua解譯器它的情況,最後從Lua中調用它並使用其結果。我在後面也將談一談Lua程式中的錯誤檢查。

定義函數

第一步是定義函數。所有在Lua中被調用的C/C++函數將使用下面一類指標進行調用:

typedef int (*lua_CFunction) (lua_State *L);

換句話說,函數必須要以Lua解譯器作為唯一的參數,並且返回一個唯一的整數。由於用一個Lua解譯器作為參數,因此函數實際上能夠從棧中取得任意數量的參數。在後面我們將看到,返回的整數實際上是被壓入棧的值的個數。通過如此容易的封裝,就能滿足你在Lua中調用C++函數的需求。

下面給出的C++函數average()示範了如何接受多個參數且返回超過一個值。記住,該函數是一個與上面typedef相匹配的函數。

  1. lua_gettop函數返回棧頂的索引值。因為在Lua中棧是從1開始編號的,因此該函數獲得的值就是參數的個數。
  2. 在for迴圈中計算所有參數之和。
  3. 調用lua_pushnumber()將參數的平均值壓棧。
  4. 將參數之和壓入棧中。
  5. 最後,函數返回2,說明有兩個傳回值在棧中。 

現在C++函數已經被定義好了,我們必須將它告訴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 = 0;
int i;
/* 迴圈求參數之和 */
for (i = 1; i <= n; i++)
{
/* 求和 */
sum += lua_tonumber(L, i);
}
/* 壓入平均值 */
lua_pushnumber(L, sum / n);
/* 壓入和 */
lua_pushnumber(L, sum);
/* 返回傳回值的個數 */
return 2;
}

int main ( int argc, char *argv[] )
{
/* 初始化Lua */
L = lua_open();
/* 載入Lua基本庫 */
luaL_openlibs(L);
/* 註冊函數 */
lua_register(L, "average", average);
/* 運行指令碼 */
luaL_dofile(L, "avg.lua");
/* 清除Lua */
lua_close(L);
/* 暫停 */
printf( "Press enter to exit…" );
getchar();
return 0;
}

下面是以5個參數調用average函數並且顯示兩個傳回值的Lua指令碼,我們將其儲存為avg.lua:

-- call a C++ function
avg, sum = average(10, 20, 30, 40, 50)
print("The average is ", avg)
print("The sum is ", sum)
編譯

在Linux下,在命令列鍵入:

g++ luaavg.cpp -llua -llualib -o luaavg

然後,鍵入下列命令運行:

./luaavg

如果沒有問題, 程式將顯示出平均值、和。

在Visual C++你將需要進行下列步驟:

  1. 建立一個新的空Win32控制台應用工程。
  2. 將"luatest.cpp"加入你的工程。
  3. 選擇項目菜單中的屬性菜單。
  4. 在"連接器"的"輸入"欄目的"附加依賴項"中輸入"lua5.1.lib"。
  5. 確定。

此時,按F7構建程式。

如果你採用的是dll庫,請確保將其放在應用程式的目錄中或者windows系統能夠找到它的地方。如果你採用的是靜態串連庫,則不需要。

錯誤處理

如果你已經閱讀了Lua的API文檔,你將看出實際上我上面的average函數沒有進行錯誤檢查。這樣做是為了更容易地講解,然而在真實的程式中你應該做一些錯誤偵測。在上面的例子中,我們至少應該檢查每個參數是不是數字。通過在for迴圈中添加下面的代碼來實現:

if (!lua_isnumber(L, i)) {
lua_pushstring(L, "Incorrect argument to 'average'");
lua_error(L);
}

添加這樣的檢查很容易,同時這樣也讓調試更容易。當處理用兩種不同語言編寫的程式的時候,這顯得相當重要。

(本文由Groov0V翻譯,轉載請指明出處!)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.