Lua precompiled code

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

相关文章
|
7月前
|
Go
Go Errors 错误处理
Go Errors 错误处理
36 1
mod_lua.cpp:37:10: fatal error: lua.h
mod_lua.cpp:37:10: fatal error: lua.h
67 0
|
Unix C语言 Linux
Lua学习---编译生成lua和luac
众所周知,Lua是一种强大的脚本语言,并且这种语言是用C语言实现的。为什么要学习这门语言?因为它可以增强我看C语言代码的功底。 我下的Lua版本是Lua5.3,关于Lua5.3的简介如下: http://www.
2579 0
|
索引 存储
lua 初接触 --- The first time use Lua for programing
  The first time use Lua for programing  Wang Xiao      1. 关于 lua 的变量类型:     lua 变量的定义与matlab有点不同:         local d , f = 5 ,10 --声明局部变量 d,f。
1098 0