Lua precompiled code

本文介绍如何使用luac工具或string.dump函数将Lua脚本编译为二进制格式,以加快加载速度并保护源代码。文章还探讨了如何通过lua解释器执行这些编译后的文件,并提供了具体的命令行示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用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.popenfile: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.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值