編譯lua5.3
cl /MD /O2 /c /DLUA_BUILD_AS_DLL *.c
ren lua.obj lua.o
ren luac.obj luac.o
link /DLL /IMPLIB:lua5.3.0.lib /OUT:lua5.3.0.dll *.obj
link /OUT:lua.exe lua.o lua5.3.0.lib
lib /OUT:lua5.3.0-static.lib *.obj
link /OUT:luac.exe luac.o lua5.3.0-static.lib
require模塊
http://cloudwu.github.io/lua53doc/manual.html#pdf-require
當請求 a.b.c 時, 它將查找 a 這個 C 庫。 如果找得到,它會在里面找子模塊的加載函數。 在我們的例子中,就是找 luaopen_a_b_c。 利用這個機制,可以把若干 C 子模塊打包進單個庫。 每個子模塊都可以有原本的加載函數名。
require不會重復加載
顯示當前加載的所有模塊
for k,v in pairs(package.loaded) do
print(k,v)
end
Lua Stack
+-----------------------+
| element with index 6 | <-- top ("relative" index -1)
+-----------------------+
| element with index 5 | <-- -2
+-----------------------+
| element with index 4 | <-- -3
+-----------------------+
| element with index 3 | <-- -4
+-----------------------+
| element with index 2 | <-- -5
+-----------------------+
| element with index 1 | <-- bottom ("relative" index -6 )
+-----------------------+
PIL
Programming in Lua
lua_call
a = f("how", t.x, 14)
lua_getglobal(L, "f"); /* function to be called */
lua_pushliteral(L, "how"); /* 1st argument */
lua_getglobal(L, "t"); /* table to be indexed */
lua_getfield(L, -1, "x"); /* push result of t.x (2nd arg) */
lua_remove(L, -2); /* remove 't' from the stack */
lua_pushinteger(L, 14); /* 3rd argument */
lua_call(L, 3, 1); /* call 'f' with 3 arguments and 1 result */
lua_setglobal(L, "a"); /* set global 'a' */
lua_setfield
void lua_setfield (lua_State *L, int index, const char *k);
做一個等價于 t[k] = v 的操作, 這里 t 是給出的索引處的值, 而 v 是棧頂的那個值。
扯淡1,lua_setfield(A,B), A一定是棧的一個位置,這個位置一定是個table,B必須是table的一個索引值,而棧頂的值賦值給這個索引值。
扯淡2,set(i,k)。set的參數i和k只是確定了table的索引位置,那個值在棧頂,也就是站上-1的位置
dynamic libraries not enabled
Error:
lua 5.3 error: dynamic libraries not enabled; check your Lua installation
Fix:
luaconf.h
#define LUA_DL_DLL
8 basic types
nil,boolean,number,string,function,userdata,thread, andtable
Light Userdata
ref:https://www.lua.org/pil/28.5.html
A light userdatum is a value that represents a C pointer (that is, avoid *value)
Light userdata are not buffers, but single pointers.They have no metatables. Like numbers, light userdata do not need to be managed by the garbage collector (and are not).
it is equal to any userdata that represents the same pointer
Userdata
The userdata type allows arbitrary C data to be stored in Lua variables.
用戶數據類型的值是一個內存塊, 有兩種用戶數據:完全用戶數據,指一塊由 Lua 管理的內存對應的對象;輕量用戶數據,則指一個簡單的 C 指針
用戶數據在 Lua 中除了賦值與相等性判斷之外沒有其他預定義的操作。
你只能通過 C API 而無法在 Lua 代碼中創建或者修改用戶數據的值
userdata 操作
lua_islightuserdata
判斷給定索引的值是一個輕量用戶數據
lua_isuserdata
判斷給定索引的值是一個用戶數據(無論是完全的還是輕量的)
lua_newuserdata
這個函數分配一塊指定大小的內存塊, 把內存塊地址作為一個完全用戶數據壓棧, 并返回這個地址。 宿主程序可以隨意使用這塊內存。
lua_pushlightuserdata
把一個輕量用戶數據壓棧。輕量用戶數據表示一個指針void*。 它是一個像數字一樣的值: 你不需要專門創建它,它也沒有獨立的元表,而且也不會被收集(因為從來不需要創建)。 只要表示的 C 地址相同,兩個輕量用戶數據就相等。
lua_touserdata
如果給定索引處的值是一個完全用戶數據, 函數返回其內存塊的地址。如果值是一個輕量用戶數據, 那么就返回它表示的指針。
冒號語法糖
冒號語法可以用來定義方法,就是說,函數可以有一個隱式的形參 self。因此,如下語句
function c:f(params) body end
是這樣一種寫法的語法糖
c.f = function(self, params) body end
也就是說,如果用冒號定義函數,則等價于給函數增加了一個隱含的形參self
當用冒號去訪問方法,相當于隱含的傳遞了一個形參self
如果希望方法引用其所屬表上的其他變量,你可以加個冒號,這相當于將方法所屬的表當作class來使用
冒號語法糖方法訪問原則
函數定義時帶冒號,則函數訪問時也帶冒號;同理,點號定義,則點號訪問
不按規矩來,則要注意了:
冒號定義方法,但卻不帶冒號訪問,則造成調用的時候,將第一個形參數賦值給self了。
可以這樣理解,當用非冒號調用,則如果定義的函數用了冒號糖,則將糖展開為function foo(self, ...) end。------吃糖要先剝紙就是這個道理
<占位標題>
<占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述>
<占位項1>
<占位項2>
<占位標題>
<占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述>
<占位項1>
<占位項2>
<占位標題>
<占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述>
<占位項1>
<占位項2>
<占位標題>
<占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述>
<占位項1>
<占位項2>
<占位標題>
<占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述占位描述>
<占位項1>
<占位項2>