lua利用乙個虛擬的堆疊來給c傳遞值或從c獲取值。每當lua呼叫c函式,都會獲得乙個新的堆疊,該堆疊初始包含所有的呼叫c函式所需要的引數值(lua傳給c函式的呼叫實參),並且c函式執行完畢後,會把返回值壓入這個棧(lua從中拿到c函式呼叫結果)。
(1)typedef struct lua_state lua_state;
lua虛擬機器(或叫直譯器),可以理解為乙個thread,和乙個完整的lua虛擬環境的執行狀態。
(2)typedef int (*lua_cfunction) (lua_state *l);
能夠被lua呼叫的c函式都必須是這種規則。函式的返回的int值表示c函式返回值的個數。
(3)void lua_pushcclosure (lua_state *l, lua_cfunction fn, int n);
將乙個c閉包壓棧;
首先將upvalues依次壓棧,然後呼叫該函式,將c函式壓棧,並將n個upvalues出棧;
引數fn:c函式指標
引數n:函式關聯的upvalue的個數。
(4)void lua_pushcfunction (lua_state *l, lua_cfunction f);
將c函式壓棧;
接收乙個c函式的指標引數,然後將乙個lua.function型別的物件壓棧。
(5)void lua_register (lua_state *l, const char *name, lua_cfunction f);
註冊c函式為乙個全域性變數;
#define lua_register(l,n,f) (lua_pushcfunction(l, f), lua_setglobal(l, n))
(6)void lual_setfuncs (lua_state *l, const lual_reg *l, int nup);
註冊函式到棧頂的表中;
引數l:lual_reg列表,記錄了要註冊的函式資訊,注意,該列表以結尾;
nup引數:upvalue的個數,如果不為0,則註冊的所有函式都共享這些upvalues;
先將table壓棧,然後將upvalues依次壓棧,然後呼叫該函式進行函式註冊。註冊完畢後upvalues會出棧。
注意:lual_register函式已經不再使用,取而代之的是lual_setfuncs,因為該函式不會建立全域性變數。
typedef struct lual_reg lual_reg;
lua可以呼叫c函式的能力將極大的提高lua的可擴充套件性和可用性。對於有些和作業系統相關的功能,或者是對效率要求較高的模組,我們完全可以通過c函式來實現,之後再通過lua呼叫指定的c函式。對於那些可被lua呼叫的c函式而言,其介面必須遵循lua要求的形式,即typedef int (*lua_cfunction)(lua_state* l)。簡單說明一下,該函式型別僅僅包含乙個表示lua環境的指標作為其唯一的引數,實現者可以通過該指標進一步獲取lua**中實際傳入的引數。返回值是整型,表示該c函式將返回給lua**的返回值數量,如果沒有返回值,則return 0即可。需要說明的是,c函式無法直接將真正的返回值返回給lua**,而是通過虛擬棧來傳遞lua**和c函式之間的呼叫引數和返回值的。這裡我們將介紹兩種lua呼叫c函式的規則。
1. c函式作為應用程式的一部分
#include #include#include
#include
#include
//待lua呼叫的c註冊函式。
static
int add2(lua_state*l)
//另乙個待lua呼叫的c註冊函式。
static
int sub2(lua_state*l)
const
char* testfunc = "
print(add2(1.0,2.0)) print(sub2(20.1,19))";
intmain()
2. c函式庫成為lua的模組
將包含c函式的**生成庫檔案,如linux的so,或windows的dll,同時拷貝到lua**所在的當前目錄,或者是lua_cpath環境變數所指向的目錄,以便於lua解析器可以正確定位到他們。在我當前的windows系統中,我將其copy到"c:\program files\lua\5.1\clibs\",這裡包含了所有lua可呼叫的c庫。見如下c語言**和關鍵性注釋:
#include #include#include
#include
#include
//待註冊的c函式,該函式的宣告形式在上面的例子中已經給出。
//需要說明的是,該函式必須以c的形式被匯出,因此extern "c"是必須的。
//函式**和上例相同,這裡不再贅述。
extern"c
"int add(lua_state*l)
extern"c
"int sub(lua_state*l)
//lual_reg結構體的第乙個欄位為字串,在註冊時用於通知lua該函式的名字。
//第乙個欄位為c函式指標。
//結構體陣列中的最後乙個元素的兩個欄位均為null,用於提示lua註冊函式已經到達陣列的末尾。
static lual_reg mylibs =,
,}; //
該c庫的唯一入口函式。其函式簽名等同於上面的註冊函式。見如下幾點說明:
//1. 我們可以將該函式簡單的理解為模組的工廠函式。
//2. 其函式名必須為luaopen_***,其中***表示library名稱。lua**require "***"需要與之對應。
//3. 在lual_register的呼叫中,其第乙個字串引數為模組名"***",第二個引數為待註冊函式的陣列。
//4. 需要強調的是,所有需要用到"***"的**,不論c還是lua,都必須保持一致,這是lua的約定,
//否則將無法呼叫。
extern"c
"__declspec(dllexport)
int luaopen_mytestlib(lua_state*l)
見如下lua**:
require"mytestlib"--
指定包名稱
--在呼叫時,必須是package.function
print(mytestlib.add(1.0,2.0
))print(mytestlib.sub(20.1,19))
參考:
C中呼叫Lua函式
我們先來看乙個簡單的例子 lua state l null 內部呼叫lua函式 double f double x,double y int main void functest.lua f function a,b return a b end 這其中最關鍵的是呼叫函式的使用,在c中呼叫lua函式...
lua呼叫c函式
最近在進入lua程式設計的狀態,一度令我困惑的是,lua提供的功能少的可憐,跟自備電池的python相比,可說是簡陋了。連table的列印,都需要自己實現,也因此有了一打的第三方方案。後來我想明白了,以lua和c如此緊密的關係,只需要建立lua的binding,那麼豐富而效能強大的c庫資源完全可以為...
lua呼叫c函式
lua可以呼叫c函式的能力將極大的提高lua的可擴充套件性和可用性。對於有些和作業系統相關的功能,或者是對效率要求較高的模組,我們完全可以通過c函式來實現,之後再通過lua呼叫指定的c函式。對於那些可被lua呼叫的c函式而言,其介面必須遵循lua要求的形式,即 typedef int lua cfu...