编译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>