Lua_State 動態結構
這個結構是虛擬機運行起來最重要的結構體
用 Lual_newstate 創建一個新的環境
lualib.h 定義了打開標準庫的函數 Lual_openlibs 可以打開所有的標準庫
創建好狀態 在加載了標準庫以後就能解釋用戶的輸入了。
Lua 和 c 的交互全在虛擬站裏面進行。
虛擬棧解決了lia和c 的兩大差異
1>lua的垃圾收集
2>c是靜態類型 lua是動態類型。
lua_loadbuffer() 函數來編譯用戶輸入的每行內容 沒有錯誤 返回0 並向棧中壓入編譯好的程序塊。
調用lua_pcall 將程序塊從棧中彈出。在保護模式中運行。返回0無錯誤。出錯會像虛擬站裏面壓入錯誤信息。
lua_pop可以將站裏的信息刪除。lua_tostring獲得這條信息。。
如果將lua作爲c來編譯 並在c++中使用,可以包含 lua.hpp 代替lua.h
lua.hpp定義 :
extern “c”{#include “lua.h”}
c包含lua類型
lua的函數參數是沒有類型的 c是要固定類型的 這個可以用union來解決
聲明一個 union 裏面裝着 所有的lua類型
例如:settable(lua_value a,lua_value k, lua_value v); //a 是表名 k是鍵值 v是實值
這樣有兩個缺點 :
1>不能將這樣的東西 映射到其他的語言
2>lua的垃圾清理機制 如果用c的這個保存變量 lua的垃圾清理檢測不到 然後把他們當成垃圾了,然後給清理了就好了。
所以 並沒有用這樣的方式實現, 而是使用了一種特殊的虛擬站 實現。
棧裏面的每一個元素都能保存任何類型的lua值。要獲取lua值的時候就調用一個lua 的 API函數。
lua將指定的值壓入棧中。將一個值傳給lua時候,先將值壓入棧。然後調用lua API lua就可以獲得值 並從棧中彈出
爲了將c類型的值壓入棧,或者從棧中獲取不同類型的值,就爲每個類型定義一個特定的函數。棧有lua管理 可以共垃圾收集器使用。
lua_loadbuffer將編譯好的程序塊或者錯誤信息留在棧中。
lua_pcall會調用棧中的一個函數
lua 按照LIFO規範來操作棧,當調用lua時候,lua只會改變棧頂。
c代碼擁有更大的自由度,比如插入刪除遍歷等等。
壓入棧函數 API
lua_pushnil(lua_state *L); //壓入nil
lua_pushboolean(lua_state *L,int bool); //壓入bool
lua_pushnumer(lua_state *L,lua_Number n); //壓入雙精度
lua_pushinteger(lua_state *L,lua_Integeter); //壓入整數
lua_pushlstring(lua_state L,const char str,size_t len); //壓入定長字符串
lua_pushstring(lua_state *L,const char *str); //壓入結尾是0的字符串
lua_Number lua_Integer是lua的兩個類型 吧 對應小數整數
lua會爲字符串創建副本而不會持有指針 所以放心操作。
lua_checkStack(lua_state *L,int sz) //檢測是否有足夠的空閒。 4 - 2 80 - 40 240 -120 -3
錯誤處理
平常代碼是 在不保護模式下進行的
當亂髮現了例如”內存不足”這樣的錯誤的時候,不會處理,而是調用一個“緊急”函數,打不過嘎不是關於發佈關於三皈依,lua就結束了,可以通過lua_aparic設置自己的”緊急”函數。
lual_newstate,lua_load,lua_pcall,lua_close是安全的,不會跑出異常。
如果發生了內存的錯誤 又不想結束程序
1>設置一個”緊急”函數,不把控制權返回給lua
2>讓代碼在“保護模式”下運行
大多數採用2 的做法 獨愛踢不過lua_pcall來運行lua代碼 這些lua代碼就是運行在保護模式下的。
在爲lua 編寫函數的時候 只有一種標準的錯誤處理方法。當c函數檢測到一個錯誤時候 就用該調用lua_error .lua_error會清理lua中所有要清理的東西,然後跳到之前要執行的Lua_pcall,並附上一條錯誤信息。