透過例子學習Lua(7)--呼叫C/C++函式(轉)

post0發表於2007-08-12
透過例子學習Lua(7)--呼叫C/C++函式(轉)[@more@]

  1.前言

  上次偶說到從C/C++中呼叫Lua的函式, 然後就有朋友問從Lua中如何呼叫C/C++的

  函式, 所以偶們這次就來說說這個問題. 首先偶們會在C++中建立一個函式, 然後

  告知Lua有這個函式, 最後再執行它. 另外, 由於函式不是在Lua中定義的, 所以

  無法確定函式的正確性, 可能在呼叫過程中會出錯, 因此偶們還會說說Lua出錯處

  理的問題.

  

  2.Lua中呼叫C函式

  在lua中是以函式指標的形式呼叫函式, 並且所有的函式指標都必須滿足如下此種

  型別:

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

  

  也就是說, 偶們在C++中定義函式時必須以lua_State為引數, 以int為返回值才能

  被Lua所呼叫. 但是不要忘記了, 偶們的lua_State是支援棧的, 所以透過棧可以

  傳遞無窮個引數, 大小隻受記憶體大小限制. 而返回的int值也只是指返回值的個數

  真正的返回值都儲存在lua_State的棧中. 偶們通常的做法是做一個wrapper, 把

  所有需要呼叫的函式都wrap一下, 這樣就可以呼叫任意的函式了.

  

  下面這個例子是一個C++的average()函式, 它將展示如何用多個引數並返回多個值

  

  例e14.cpp

  #include

  

  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, "e15.lua");

  

  /* cleanup Lua */

  lua_close(L);

  

  return 0;

  }

  

  例e15.lua

  -- call a C++ function

  

  avg, sum = average(10, 20, 30, 40, 50)

  

  print("The average is ", avg)

  print("The sum is ", sum)

  

  

  程式說明:

  * lua_gettop()的作用是返回棧頂元素的序號. 由於Lua的棧是從1開始編號的,

   所以棧頂元素的序號也相當於棧中的元素個數. 在這裡, 棧中元素的個數就

   是傳入的引數個數.

  * for迴圈計算所有傳入引數的總和. 這裡用到了數值轉換lua_tonumber().

  * 然後偶們用lua_pushnumber()把平均值和總和push到棧中.

  * 最後, 偶們返回2, 表示有兩個返回值.

  * 偶們雖然在C++中定義了average()函式, 但偶們的Lua程式並不知道, 所以需

   要在main函式中加入

  

    /* register our function */

  lua_register(L, "average", average);

  

   這兩行的作用就是告訴e15.lua有average()這樣一個函式.

  * 這個程式可以存成cpp也可以存成c, 如果以.c為副檔名就不需要加extern "C"

  

  編譯的方法偶們上次說過了, 方法相同.

  e15.lua執行的方法只能用上例中的C++中執行, 而不能用命令列方式執行.

  

  3.錯誤處理

  在上例中, 偶們沒有對傳入的引數是否為數字進行檢測, 這樣做不好. 所以這裡偶

  們再加上錯誤處理的片斷.

  

  把這段加在for迴圈之內:

  if (!lua_isnumber(L, i)) {

  lua_pushstring(L, "Incorrect argument to 'average'");

  lua_error(L);

  }

  這段的作用就是檢測傳入的是否為數字.

  

  加上這段之後, 偶們debug的時候就會簡單許多. 對於結合兩種語言的程式設計, 它們之

  間傳遞資料的正確性檢測是非常重要的.

  

  這裡有別人寫好的例子:

  VC的

  Linux的

 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/8225414/viewspace-951599/,如需轉載,請註明出處,否則將追究法律責任。

相關文章