Lua與C交互之基礎操作(1)


@(語言)

Lua是一個嵌入式的語言,可以Lua可以作為程序庫用來擴展應用的功能,也可以注冊有其他語言實現的函數,這些函數可能由C語言(或其他語言)實現,可以增加一些不容易由Lua實現的功能。這就是Lua這幾年在收集游戲開發領域飛速的發展使用的原因,便於熱更新,尤其使在IOS平台上。這篇文章主要是自己在學習過程中的一些記錄,主要參考<Lua程序設計>一書第二版。

1. 交互棧

在使用過程中,雖然在游戲中我們把lua作為腳本來用,這幾年手機游戲其實大量的邏輯都在lua上進行,包括戰斗邏輯。盡管如此,使用過程中都會涉及到Lua和其他語言之間的互相調用。在C和Lua之間通信關鍵內容在於一個虛擬的棧。

棧是一個嚴格FIFO規則,每條記錄可以是任何類型。而幾乎所有的API調用都是對棧上的值進行操作,所有C與Lua之間的數據交換也都通過這個棧來完成,也可以使用棧來保存臨時變量。棧的使用解決了C和Lua之間兩個不協調的問題:第一,Lua會自動進行垃圾收集,而C要求顯示的分配存儲單元,兩者引起的矛盾。第二,Lua中的動態類型和C中的靜態類型不一致引起的混亂。

棧中的每一條記錄都可以保存任何 Lua 值。當你想要從 Lua 請求一個值時,Lua會將請求的值將會被壓入棧。當你想要傳遞一個值給 Lua,首先將這個值壓入棧,然后調用 Lua(這個值將被彈出)。

# 數據類型

可以參考Lua數據類型實現源碼解析 一文, Lua包含值類型boolean、number、string、userdata、function、thread和table。實際在底層實現中可以根據下圖理解。
mark

索引

操作過程中基本都是對站定就行操作,棧的索引可以使用正索引或者負索引,即在不知道棧大小的情況下,正數索引1永遠表示棧底,負數索引-1永遠表示棧頂。
mark

棧大小

luaconfig中是可以配置的(似乎)。默認是20,一般在函數操作過程中,需要維護棧的大小不會無限擴展下去,比如在函數調用后及時的清理。

2. 基本操作

壓入棧

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);
void lua_pushcclosure(lua_State *L, lua_CFunction fn, int n);

查詢元素

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);
size_t lua_strlen (lua_State *L, int index);
void *lua_touserdata(lua_State*L,intindex)

維護棧

//返回堆棧中的元素個數
int lua_gettop (lua_State *L);
//設置棧頂為一個指定的值,如果開始的棧頂高於新的棧頂,頂部的值被丟棄
void lua_settop (lua_State *L, int index);  
//壓入指定索引的一個摶貝到棧頂 
void lua_pushvalue (lua_State *L, int 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_getfield/lua_setfield

void  lua_getfield (lua_State *L, int index , const char *k);

Pushes onto the stack the value t[k], where t is the value at the given valid index index
index 是table變量在棧中的索引值,k是table的鍵值,執行成功后將字段值壓入棧中。

void lua_setfield (lua_State *L, int index, const char *k);

Does the equivalent to t[k] = v, where t is the value at the given valid index index and v is the value at the top of the stack,This function pops the value from the stack。
index 是table變量在棧中的索引值,k是table的鍵值,v為棧頂元素,執行成功后將棧頂元素彈出。

lua_getglobal /lua_setglobal
// #define lua_getglobal(L,s)  lua_getfield(L, LUA_GLOBALSINDEX, s)
void lua_getglobal (lua_State *L, const char *name);

將全局表中s索引對應的元素壓入棧

//  #define lua_setglobal(L,s)   lua_setfield(L, LUA_GLOBALSINDEX, s)
void lua_setglobal (lua_State *L, const char *name);

將棧頂賦值給全局中s索引對應的元素,並彈出棧頂

lua_gettable/lua_settable
void lua_gettable (lua_State *L, int index);

Pushes onto the stack the value t[k], where t is the value at the given valid index index and k is the value at the top of the stack. This function pops the key from the stack (putting the resulting value in its place).
把t[k] 值壓入堆棧,這里的 t 是指有效索引 index 指向的值,而 k 則是棧頂放的值。這個函數會彈出堆棧上的 key,把結果放在棧上相同位置。

void lua_settable (lua_State *L, int index);

Does the equivalent to t[k] = v, where t is the value at the given valid index index, v is the value at the top of the stack, and k is the value just below the top.This function pops both the key and the value from the stack.ue from the stack.
作一個等價於 t[k] = v 的操作,index 是table變量在棧中的索引值,v 為棧頂的值, k 是棧頂之下的元素。執行成功后把鍵和值都從堆棧中彈出。

lua_rawset / lua_rawget
void lua_rawget (lua_State *L, int index);  
void lua_rawset (lua_State *L, int index);  

與 lua_gettable/lua_settable類似,不過不會操作metamethods, 操作的Key/Value都在棧頂,棧頂是Value,第二個是Key'

lua_rawgeti /lua_rawseti
void lua_rawgeti (lua_State *L, int index, int n);
void lua_rawseti (lua_State *L, int index, int n);

與lua_getfield/lua_setfield類似,不過不會操作metamethods
lua_rawgeti 相當於:
lua_pushnumber(L, key); lua_rawget(L, t);
lua_rawseti 相當於:lua_pushnumber(L, key); lua_insert(L, -2); lua_rawset(L, t);

int luaL_getmetafield (lua_State *L, int obj, const char *e);

Pushes onto the stack the field e from the metatable of the object at index obj. If the object does not have a metatable, or if the metatable does not have this field, returns 0 and pushes nothing.

結束

表操作其實有很多可以介紹,尤其是涉及到metatable這塊,后續補充。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM