Lua和C語言的互動 C API

2022-02-08 06:01:36 字數 4542 閱讀 8780

lua可作為擴充套件性語言(lua可以作為程式庫用來擴充套件應用的功能),同時也是個可擴充套件的語言(lua程式中可以註冊由其他語言實現的函式)。

c和lua互動的部分稱為c api。c api是乙個c**與lua進行互動的函式集。他由以下部分組成:

讀寫lua全域性變數的函式、

呼叫lua函式的函式、

執行lua**片斷的函式、

註冊c函式然後可以在lua中被呼叫的函式,等等。

api中有些函式為了方便以巨集的方式實現。

當在lua和c之間交換資料時我們面臨著兩個問題:動態與靜態型別系統的不匹配和自動與手動記憶體管理的不一致。解決辦法是在c和lua之間通訊關鍵在於乙個虛擬的棧。幾乎所有的api呼叫都是對棧上的值進行操作,所有c與lua之間的資料交換也都通過這個棧來完成。因為棧是由lua來管理的,垃圾**器知道那個值正在被c使用。

lua以乙個嚴格的lifo規則(後進先出;也就是說,始終訪問棧頂)來操作棧:

(1)當你呼叫lua時,它只會改變棧頂部分。

(2)你的c**卻有更多的自由;更明確的來講,你可以查詢棧上的任何元素,甚至是在任何乙個位置插入和刪除元素。

在呼叫c api時有幾個重要的標頭檔案:

(1)lua.h:lua基礎函式庫,lua_字首

(2)lauxlib.h:輔助庫,lual_字首,利用lua.h實現的更高層的抽象

(3)lualib.h:為了保持lua的苗條,所有的標準庫以單獨的包提供,所以如果你不需要就不會強求你使用它們。標頭檔案lualib.h定義了開啟這些庫的函式。例如,呼叫luaopen_io,以建立io table並註冊i/o函式(io.read,io.write等等)到lua環境中。

api用索引來訪問棧中的元素。棧底為1,依次往上增加,也可用負數索引,-1表示棧頂元素。下面列出一些常用的c api函式:

lua_push*:壓入棧元素

void lua_pushnil (lua_state *l);

void lua_pushboolean (lua_state *l, int bool);

void lua_pushnumber (lua_state *l, double n);

void lua_pushlstring (lua_state *l, const char *s, size_t length);

void lua_pushstring (lua_state *l, const char *s);

lua_to*:從棧中獲得值。即使給定的元素型別不正確,呼叫這些函式也沒問題。

int lua_toboolean (lua_state *l, int index);

double lua_tonumber (lua_state *l, int index);

const char * lua_tostring (lua_state *l, int index);

lua_tostring函式返回乙個指向字串的內部拷貝的指標。你不能修改它(使你想起那裡有乙個const)。只要這個指標對應的值還在棧內,lua會保證這個指標一直有效。當乙個c函式返回後,lua會清理他的棧,所以,有乙個原則:永遠不要將指向lua字串的指標儲存到訪問他們的外部函式中。

size_t lua_strlen (lua_state *l, int index):返回字串的實際長度。

int lua_checkstack(lua_state *l, int sz):檢查棧空間。預設有20個空閒的記錄,lua.h中的lua_minstack巨集定義了這個常量。

int lua_is... (lua_state *l, int index):檢查乙個元素能否被轉換成指定的型別。

int lua_type (lua_state *l, int idx):返回棧中元素的型別;

const char* lua_typename(lua_state *l, int tp):返回type對應的名字字串,第二個引數為lua_type返回的型別

void lual_checktype (lua_state *l, int arg, int t):返回引數arg是否是型別t,第三個引數為lua_type的取值。

在lua.h標頭檔案中,每種型別都被定義為乙個常量:lua_tnil、lua_tboolean、lua_tnumber、lua_tstring、lua_ttable、lua_tfunction、lua_tuserdata以及lua_tthread。

int lua_gettop (lua_state *l):返回棧中元素個數,它也是棧頂元素的索引。

void lua_settop (lua_state *l, int index):設定棧頂元素的索引,相當於設定棧的大小。如果開始的棧頂高於新的棧頂,頂部的值被丟棄。否則,為了得到指定的大小這個函式壓入相應個數的空值(nil)到棧上。lua_settop(l,0):清空堆疊。

#define lua_pop(l,n) lua_settop(l, -(n)-1):巨集定義,彈出n個元素。

void lua_pushvalue (lua_state *l, int index):壓入堆疊上指定索引的乙個摶貝到棧頂,等於拷貝index處的元素,然後新增到棧頂。

void lua_remove (lua_state *l, int index):移除指定索引的元素,並將其上面所有的元素下移來填補這個位置的空白。

void lua_insert (lua_state *l, int index):移動棧頂元素到指定索引的位置,並將這個索引位置上面的元素全部上移至棧頂被移動留下的空隔。

void lua_replace (lua_state *l, int index):從棧頂彈出元素值並將其設定到指定索引位置,沒有任何移動操作。

下面來看一段lua和c++簡單互動的**:

#include #include 

extern"c

" int main (void

) }

lua_close(l);

return0;

}

上述**在vs2010中正常執行,lua使用5.1的版本,其中有幾點需要注意的:

(1)lua5.0之前初始化庫的用法如下:

luaopen_base(l); /*

opens the basic library

*/luaopen_table(l);

/*opens the table library

*/luaopen_io(l);

/*opens the i/o library

*/luaopen_string(l);

/*opens the string lib.

*/luaopen_math(l);

/*opens the math lib.

*/

但5.0之後只需要一句話即可:

lual_openlibs(l);

(2)需要新增依賴庫:lua5.1.lib lua51.lib。

下面這個例子可以有助於加深對c和lua之間堆疊的理解:

//

從棧底到棧頂依次遍歷整個堆疊

static

void stackdump(lua_state*l)

printf(""

); }

printf("\n

");}int main(void

)

注意lua_replace首先會彈出棧頂元素,並且需要注意的是lua_replace(l, -1);語句會導致站頂元素彈出,其他元素不變。

作為配置語言是lua的乙個重要應用,下面看乙個簡單的這方面的例子。有乙個含有簡單字段記錄的lua檔案如下:

width = 200

height = 300

對該lua檔案的解析大媽如下:

#include #include #include #include extern "c

" void

error(lua_state* l, const char*fmt, ...)

void

load(char* filename, int* width, int*height)

lua_getglobal(l,

"width");

lua_getglobal(l,

"height");

if(!lua_isnumber(l, -2

))

error(l, "

'width' should be a number\n");

if(!lua_isnumber(l, -1

))

error(l, "

'height' should be a number\n");

*width = (int)lua_tonumber(l, -2

); *height = (int)lua_tonumber(l, -1

); lua_close(l);

}int main(void)

Lua和C語言的互動(一)

lua生來就是為了和c互動的,因此使用c擴充套件lua或者將lua嵌入到c當中都是非常流行的做法。要想理解c和lua的互動方式,首先要回顧一下c語言是如何處理函式引數的。c函式和引數 大家知道c語言是用彙編實現的,在組合語言中可沒有函式的概念,與函式對應的是叫做子過程的東西,子過程就是一段指令,乙個...

Lua和C語言的互動(一)

lua生來就是為了和c互動的,因此使用c擴充套件lua或者將lua嵌入到c當中都是非常流行的做法。要想理解c和lua的互動方式,首先要回顧一下c語言是如何處理函式引數的。c函式和引數 大家知道c語言是用彙編實現的,在組合語言中可沒有函式的概念,與函式對應的是叫做子過程的東西,子過程就是一段指令,乙個...

Lua和C 語言的互動詳解

前言 寫過windows程式的人都知道,對於應用程式,如果需要在本地儲存一些配置資訊,我們經常將這些配置資訊寫在登錄檔或者本地的配置檔案中,很多應用都是將一些配置資訊寫在配置檔案中,比如以ini結尾的檔案,這種配置檔案很多,使用的很廣泛,然後應用程式在啟動的時候,就會解析這個配置檔案,讀取一些配置資...