使用luac或者string.dump函数可以将Lua脚本编译成二进制格式, 编译后的代码同样可以使用lua运行.
预编译代码(二进制格式)加载速度比文本快, 但是文件可能更大, 同时二进制格式可以对代码起到一定的保护作用, 因为文本很容易暴露或被修改.
# vi test.lua
local a=1
function f() a=a+1 return a end
for i=1,20 do
print(f())
end
使用luac把脚本转换成二进制编码
# luac -o ./test.lc test.lua
二进制文件test.lc和文本test.lua都可以使用lua执行
[root@db-172-16-3-150 ~]# lua ./test.lc
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@db-172-16-3-150 ~]# lua ./test.lua
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
使用luac -l可以查看lua或lc文件的虚拟机指令.
produce a listing of the compiled bytecode for Lua’s virtual machine. Listing bytecodes is useful to learn about Lua’s virtual machine. If no files are given, then luac loads luac.out and lists its con tents.
[root@db-172-16-3-150 ~]# luac -l ./test.lc
main <test.lua:0,0> (13 instructions at 0x8673c0)
0+ params, 7 slots, 1 upvalue, 5 locals, 4 constants, 1 function
1 [1] LOADK 0 -1 ; 1
2 [2] CLOSURE 1 0 ; 0x867570
3 [2] SETTABUP 0 -2 1 ; _ENV "f"
4 [3] LOADK 1 -1 ; 1
5 [3] LOADK 2 -3 ; 20
6 [3] LOADK 3 -1 ; 1
7 [3] FORPREP 1 4 ; to 12
8 [4] GETTABUP 5 0 -4 ; _ENV "print"
9 [4] GETTABUP 6 0 -2 ; _ENV "f"
10 [4] CALL 6 1 0
11 [4] CALL 5 0 1
12 [3] FORLOOP 1 -5 ; to 8
13 [5] RETURN 0 1
function <test.lua:2,2> (6 instructions at 0x867570)
0 params, 2 slots, 1 upvalue, 0 locals, 1 constant, 0 functions
1 [2] GETUPVAL 0 0 ; a
2 [2] ADD 0 0 -1 ; - 1
3 [2] SETUPVAL 0 0 ; a
4 [2] GETUPVAL 0 0 ; a
5 [2] RETURN 0 2
6 [2] RETURN 0 1
使用string.dump这个函数可以将函数打包成二进制代码, 与luac的效果一致.
例如使用loadfile把lua文件加载为一个匿名函数, 然后使用string.dump转换成二进制代码.
使用io.open 和 file:write 写入文件.
例如 :
> p = loadfile("/root/test.lua") -- 加载文件, 输出一个匿名函数
> f = io.open("/root/test.lc", "wb") -- 以写模式和二进制模式打开文件
> f:write(string.dump(p)) -- 使用file:write写文件, string.dump(p) 将函数转换成二进制格式
> f:close() -- 关闭文件
> os.exit()
[root@db-172-16-3-150 ~]# lua test.lc
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
这个稍加修改就可以改成一个类似luac的脚本.
[root@db-172-16-3-150 ~]# vi luac.lua
p = loadfile(arg[1])
f = io.open(arg[2], "wb")
f:write(string.dump(p))
f:close()
使用这个脚本打包二进制文件.
[root@db-172-16-3-150 ~]# lua ./luac.lua "/root/test.lua" "/root/test.lc"
[root@db-172-16-3-150 ~]# ll /root/test.lc
-r-x------ 1 root root 495 Feb 19 14:36 /root/test.lc
[root@db-172-16-3-150 ~]# lua /root/test.lc
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
load和loadfile支持加载文本模式或二进制格式的编码, 默认同时允许. 例如 :
> f = loadfile("/root/test.lc","t") -- "t"表示text模式, 显然加载二进制格式的test.lc会失败
> f()
stdin:1: attempt to call global 'f' (a nil value)
stack traceback:
stdin:1: in main chunk
[C]: in ?
> f = loadfile("/root/test.lc","b")
> f()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[参考]
1. man luac
2.
string.dump (function)
Returns a string containing a binary representation of the given function, so that a later load
on this string returns a copy of the function (but with new upvalues).
3.
load (ld [, source [, mode [, env]]])
Loads a chunk.
If ld
is a string, the chunk is this string. If ld
is a function, load
calls it repeatedly to get the chunk pieces. Each call to ld
must return a string that concatenates with previous results. A return of an empty string, nil, or no value signals the end of the chunk.
If there are no syntactic errors, returns the compiled chunk as a function; otherwise, returns nil plus the error message.
If the resulting function has upvalues, the first upvalue is set to the value of env
, if that parameter is given, or to the value of the global environment. (When you load a main chunk, the resulting function will always have exactly one upvalue, the _ENV
variable (see §2.2). When you load a binary chunk created from a function (see string.dump
), the resulting function can have arbitrary upvalues.)
source
is used as the source of the chunk for error messages and debug information (see §4.9). When absent, it defaults to ld
, if ld
is a string, or to "=(load)
" otherwise.
The string mode
controls whether the chunk can be text or binary (that is, a precompiled chunk). It may be the string "b
" (only binary chunks), "t
" (only text chunks), or "bt
" (both binary and text). The default is "bt
".
4.
file:write (···)
Writes the value of each of its arguments to file
. The arguments must be strings or numbers.
In case of success, this function returns file
. Otherwise it returns nil plus a string describing the error.
5.
file:close ()
Closes file
. Note that files are automatically closed when their handles are garbage collected, but that takes an unpredictable amount of time to happen.
When closing a file handle created with io.popen
, file:close
returns the same values returned by os.execute
.
6.
io.open (filename [, mode])
This function opens a file, in the mode specified in the string mode
. It returns a new file handle, or, in case of errors, nil plus an error message.
The mode
string can be any of the following:
- "
r
": read mode (the default); - "
w
": write mode; - "
a
": append mode; - "
r+
": update mode, all previous data is preserved; - "
w+
": update mode, all previous data is erased; - "
a+
": append update mode, previous data is preserved, writing is only allowed at the end of file.
The mode
string can also have a 'b
' at the end, which is needed in some systems to open the file in binary mode.