2009-08-15 154 views
4

我目前正在實施的Lua成我工作的一個應用程序。目前我只使用C api並使用lua_register註冊函數,但我希望能夠將靜態和非靜態函數指針傳遞給某些類方法。Lua腳本執行

我發現在網絡上某些庫,但因爲我需要很少的整體功能他們提供我在想,如果有一個簡單的方法來做到這一點。

謝謝。

+0

你實際上有什麼問題lua_register?它是否被宣佈爲staric的函數的可見性? – 2009-08-17 09:30:06

回答

4

複雜庫API通常可以迅速包裹和(幾乎)完全使用SWIG。在這種情況下使用SWIG的一個優點是,構建基於SWIG的包裝器很容易,可以使用包括Lua,Perl,Python,Ruby和Java等在內的18 major languages庫。

如果Lua是您首選的(也可能是唯一的)關注點,那麼我建議學習使用luaL_register()作爲策略的核心,在C中構建Lua模塊。以這種方式構建模塊的優點是您可以保留所有的功能都在一個名字空間中,沒有任何開銷。你將需要製作一個匹配Lua C函數調用約定的包裝函數(就像你使用lua_register()一樣),並從棧中收集Lua參數,調用包裝函數,並將任何返回值和出參數推回到Lua堆棧。關於如何去做的一個很好的概述可以在Lua的Programming中找到。第一版的在線副本在Chapter 26中討論了庫創建,但是是爲Lua 5.0編寫的。我強烈要求任何人認真使用Lua擁有當前版本的PiL的副本。

不幸的是,Lua 5.1與5.0最大的區別在於模塊(C和Lua)的動態加載與require

下面是一個C庫,在Lua 5.1工作的完成(如果小)的例子。我們先從包裝的C文件的執行情況:特別

#include <lua.h> 
#include <luaxlib.h> 
#include <math.h> 
#undef PI 
#define PI (3.14159265358979323846) 

static int l_sin (lua_State *L) { 
    double r = luaL_checknumber(L,1); 
    lua_pushnumber(L, sin(r)); 
    return 1; 
} 

static int l_cos (lua_State *L) { 
    double r = luaL_checknumber(L,1); 
    lua_pushnumber(L, cos(r)); 
    return 1; 
} 

static const struct luaL_reg smlib [] = { 
    {"sin", l_sin}, 
    {"cos", l_cos}, 
    {NULL, NULL} /* sentinel */ 
}; 

int luaopen_sm (lua_State *L) { 
    luaL_openlib(L, "sm", smlib, 0); 
    lua_pushnumber(L,PI); 
    lua_rawset(L,-2,"pi"); 
    return 1; 
} 

注意,需要導出的唯一功能是luaopen_sm(),其名稱必須與將與require使用的模塊的名稱以及DLL文件的名稱。編譯爲一個名爲sm.dll的DLL文件(可能命名的類Unix系統libsm.so),那麼它可以被加載並在一個Lua腳本中使用這樣的:

 
require "sm" 
print(sm.sin(sm.pi/3), sm.cos(sm.pi/3)); 

這個例子,雖然未經測試,應該編譯跑。有關從math.h包裝大多數函數的完整示例,請參閱隨Lua分發的source to the math module。由於這些薄包裝包含大量重複代碼,因此只有每個函數聲明時,SWIG等工具才能創建它們。

C++類的包裝方法在原則上是相似的。每個的Lua-調用包裝函數將要需要,可以在C++側被映射到this一個參數,它必須被實現爲一個模塊靜電功能或靜態成員函數也定位目標對象實例以及轉換其他論點。 SWIG在構造這種包裝材料方面特別擅長,並且沿途隱藏了許多血管細節。