最近讀了點lua的原始碼,打算記錄下來,將來也知道自己這一段幹了啥。
其實我以前也試圖讀過lua原始碼,不過一直沒有找對下手方向,比如我一直試圖從main下手,這個是錯誤的,還沒有進行正題,就被一大堆初始化給搞暈了,加之決心不大,就這樣一直拖著沒有看。
不過最近因為工作的原因,熟悉了lua的c api,發現從c api入手是個不錯的方法。但是首先,還是要熟悉下lua裡面的基礎資料結構:
/*** tagged values
*/#define tvaluefields value value; int tt
typedef struct lua_tvalue tvalue;
lua裡面所有的值都是存放在tvalue裡的,tvalue是所謂的tagged values。tt域表示的是值的型別(lua的8種基本型別),value域是表示具體的值,這個是乙個union,
/*** union of all lua values
*/typedef union value;
關於這兩個結構,可以瀏覽下lobject.h,裡面有詳細的說明和lua裡面的用法,通過巨集來操作。
lstate.h裡有global_state,這個是整個執行環境中只有乙份的。lua_state,表示每個thread(這是乙個coroutine,並非posix意義上的thread)的state。還有gcobject,lua有gc機制,gcobject包括了table, userdata(重型),string, function和thread。
/*** union of all collectable objects
*/union gcobject ;
接下來就從lapi.c這個檔案起。
static tvalue *index2adr (lua_state *l, int idx)
else if (idx > lua_registryindex)
else switch (idx)
case lua_globalsindex: return gt(l);
default: }}
lua和c互動方式比較特別,是通過乙個虛擬棧來互動的,通過閱讀lapi.c,可以了解下這個虛擬棧的運作,為更深入的理解lua source打基礎,這個index2adr的函式,是基礎中的基礎,它定義了棧的標識(即index)是如何轉化為實際的位址的。
如果idx > 0,那麼從棧底開始向上算,如果idx <= 0還大於lua_registryindex(-10000),那麼從棧頂開始向下數,棧上每個元素都是乙個指向tvalue的指標。
同時,這個函式還可以處理pseudo-indices,這是一類特殊的index,這個index不表示棧上的值,而表示lua registry,這個是乙個全域性的表,只對程式設計師可見,lua指令碼沒有辦法使用。lua_environindex和globalsindex來取執行時環境表和全域性表,最後還有一招,似乎很少有人使用,就是可以取當前函式的upvalue,第n個upvalue就是用lua_globalsindex - n。
另外,這裡最最重要的一點是,按照文件,傳入-1表示的是棧頂元素,也就是說l->top-1是棧頂元素,l->top表示棧上下乙個待使用空間。
接下來一段都比較好懂,直到
lua_api int lua_checkstack (lua_state *l, int size)
lua_unlock(l);
return res;
}
這裡出現了個l->ci->top,ci是個callinfo結構,看source code上的注釋是表示當前的執行的函式的資訊。l->ci->top和l->top的關係是什麼,我現在還沒有把原始碼看完,不敢下定論,我的感覺是l->ci->top表示了當前函式最多需要使用的棧空間,我就用到l->ci->top,不需要更多了。
接下來的函式又比較簡單,順著讀就可以了。不要受**,一層一層**看下去,人腦不是電腦,管理不了那麼多層遞迴。我覺得這些函式中值得一提的是
lua_api void lua_insert (lua_state *l, int idx)
這個函式名為insert,實際上棧上並沒有增加新的元素,不過是將棧頂的值交換到idx位置,而在l->top上那個元素處於無人管理的狀態,等待gc**。
在lua_call函式之前有乙個巨集
#define checkresults(l,na,nr) \
api_check(l, (nr) == lua_multret || (l->ci->top - l->top >= (nr) - (na)))
佐證了我之前的想法,棧上預留的空間,要大於返回值的個數減掉引數的個數。
Pytorch原始碼注釋
field類為可以由張量表示的常見文字處理資料型別建模。它包含乙個vocab物件,用於定義字段元素的可能值集及其對應的數字表示。field物件還包含與資料型別應如何數位化有關的其他引數,例如標記化方法和應生成的tensor型別。如果在資料集中的兩列之間共享字段 例如,qa資料集中的問題和答案 則它們...
devmem 原始碼注釋
include include include include include include include include include include include define fatal do while 0 define map size 4096ul define map mask...
lua 原始碼編譯
對於乙個開源工程,開始學習它的第一步自然是編譯工程。使用vc編譯lua,在網上已有許多介紹,但 紙上得來終覺淺 自己走一遍還是有必要的。步驟如下 2.開啟vc建立乙個solution,就叫lua.sln 3.建立乙個名為liblua的project lua庫 新增除lua.c和luac.c以外的所有...