LUA脚本语言的简介

脚本语言

脚本语言是解除硬编码,防止重编译的利器,较流行的脚本语言有Python,Lua,Ruby等。

本文章主要说说Lua。


 脚本语言存在的意义

在之前写OpenGL程序的时候,会写一个config文件配置当前程序,config文件中主要储存着程序的相关信息,在启动程序的时候,就可以解析这个config程序,找到所需要的信息。

比如解析一个json文件:

1 "model":{
2   "position":[1,1,1]
3 },
4 "light":{
5   "position":[2,2,2],
6   "intensity":3
7 }

但是这样的表达方式太过于死板,不能表达一些逻辑,比如以下的lua代码表达了角色死亡时候的逻辑:

1 if player:is_dead() then
2     do_something()
3 else
4     do_else()
5 end

更为重要的是,在修改了lua代码之后,完全不需要重新编译之前的程序代码,这也就是lua脚本语言存在的意义。


 链接库、解释器和编译器

lua是开源的,其源代码是纯c写的,因此如果想在c项目中嵌入lua代码有以下两种方式:

1 . 把lua的源代码包含到c项目中

2. 把lua源代码编译成链接库,要使用的时候直接包含链接库和必要的头文件即可。

 

如果想要单独的执行lua文件,比如在命令行中交互式的执行lua语句,则需要生成对应的lua解释器和lua编译器。

lua解释器

编译lua源代码之后就会生成一个lua.exe文件,这个文件就是lua解释器。

解释器是一个独立的可执行程序,它能够直接执行一个 lua 源文件,比如:

lua.exe hello.lua;也能够直接执行一个 lua 语句

- 双击运行 lua.exe 之后会打开一个命令行窗口,在窗口中输入 print "hello world",可以看到屏幕上输出了 hello world,即 lua 解释器执行了这条语句

lua 是一门脚本语言,和许多脚本语言一样,lua 代码并不需要经过编译就可以直接运行,解释器的作用就是直接运行源代码。 

lua编译器

lua虽然是一门解释性的脚本语言,但其实 lua 代码也是可以被编译成二进制字节码的,编译 lua 代码就需要使用到 lua 编译器 luac.exe。编译后的 lua 代码文件同样可以使用 lua 解释器来执行或者嵌入到 c 程序中,只不过它不再是源代码的格式,而是二进制文件,这可应用于代码加密。

lua链接库

如果想在 c 程序中嵌入 lua 代码,则需要 lua CAPI 的支持,一种较好的方式是把lua源代码编译成链接库,主要在每次使用的时候就不需要把源代码包含进来了。

链接库分为静态链接库和动态链接库两种,在Windows下分别为lib文件和dll文件,在Linux下分别为.a文件和so(share object)文件,具体可参见这篇文章:

http://www.cnblogs.com/dongzhiquan/archive/2010/07/22/1994587.html

https://blog.csdn.net/liuweiyuxiang/article/details/81502990

 

静态链接库和动态链接库都是代码共享的方式。

静态链接库:在链接的步骤中,链接器从库文件中取得所需的代码,复制到生成的可执行文件中,可执行文件中包含了库代码的一份完整的拷贝;缺点是被多次使用旧有多份冗余拷贝。即静态库中的指令都全部被包含在最终生成的EXE文件中,在VS中生成的静态库工程中,编译成功之后,只产生一个.lib文件(该lib中包含函数代码的索引和实现,在编译的时候直接将代码加入程序中)。

  静态链接库的好处是用户在运行的时候不要挂载动态库了,但是会导致应用程序偏大,会失去动态库的灵活性,在版本升级的时候要发布全新的应用程序。

 

动态链接库:动态链接库是一个包含可由多个程序同时使用的代码和数据的库。动态链接库提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个DLL中,该DLL包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。在VS中生成的动态库工程中,编译成功之后,产生一个.lib文件(该lib文件中包含了函数所在的DLL文件和DLL文件中函数位置的索引,函数实现由运行时加载在进程中的dll提供)和.dll文件。

  dll文件中包含实际的函数和数据,应用程序使用lib文件链接到所需要的dll文件,dll中的函数和数据并不复制到可执行文件中,在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中所要调用的函数的内存地址。

 

lib是编译的时候用到的,dll是运行时用到的。

在C++中运行Lua解释器

使用lua的链接库在你的代码中运行lua解释器:

//这是lua所需的三个头文件
//当然,你需要链接到正确的lib
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"

int main(int argc, char *argv[])
{
    lua_State *L = lua_open();
    luaopen_base(L); 
    luaopen_io(L);

    const char *buf = "print('hello, world!')";

    lua_dostring(buf);

    lua_close(L);

    return 0;
}

此时程序输出:hello, world!

有时可能需要执行一个文件,可以这么来做:

lua_dofile(L, "test.lua");

lua解释器自身维护一个运行时栈,通过此运行时栈,lua解释器向主机程序传递参数,主要就可以得到一个脚本变量的值。

lua定义了一个宏可以简单的取出一个变量的值:

lua_getglobal(L,name);

我们可以使用这个宏取得一个变量的值:

lua_getglobal(L,"var");

int var = lua_tonumber(L,-1);


 

假如在lua脚本中定义了这样一个函数:

function main(number)
    number = number + 1
    return number
end

在lua中,函数也是一个变量,可以这样获取一个函数:

lua_getglobal(L,"main")//函数现在在栈顶

现在,我们来调用这个函数,并传递给它正确的参数:

lua_pushnumber(L,100);//将函数压入栈顶

lua_pcall(L, 1, 1, 0); //调用函数,有一个参数,一个返回值

//返回值现在栈顶

int result = lua_tonumber(L, -1);

result 就是函数的返回值


 

 

 

ref

https://blog.csdn.net/gogo0304/article/category/87452

posted on 2018-10-29 11:03  whpointz  阅读(1425)  评论(0编辑  收藏  举报

导航