简介
Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。
特点
- 轻量级: 它用标准C语言编写并以源代码形式开放,编译后仅仅一百余K,可以很方便的嵌入别的程序里。
- 可扩展: Lua提供了非常易于使用的扩展接口和机制:由宿主语言(通常是C或C++)提供这些功能,Lua可以使用它们,就像是本来就内置的功能一样。
- 其它特性
- 支持面向过程(procedure-oriented)编程和函数式编程(functional programming);
- 自动内存管理;只提供了一种通用类型的表(table),用它可以实现数组,哈希表,集合,对象;
- 语言内置模式匹配;闭包(closure);函数也可以看做一个值;提供多线程(协同进程,并非操作系统所支持的线程)支持;
- 通过闭包和table可以很方便地支持面向对象编程所需要的一些关键机制,比如数据抽象,虚函数,继承和重载等。
实例
实验目的
使用lua脚本调用c动态库接口。
lua解释器
流程分析
lua解释器的流程:
- 预读lua脚本文件,将脚本中信息入栈(函数映射、语法映射);
- 函数调用时逐一出栈;
核心:数据交换。lua的一切运算都是在堆栈上完成的,这个堆栈使lua与c/c++等语言交换数据的手段。
处理流程如下图所示:
lua与c/c++等语言交换数据的堆栈定义:lua_State。
- 栈中的每一条记录都可以保存任何lua值;
- 如果想传递一个值给lua,首先将该值压栈,然后调用lua;
- 栈由lua管理,lua使用自动内存管理机制,通过垃圾回收器回收内存;
代码示例
// lua脚本加载流程
lua_State* lua = luaL_newstate();
luaL_openlibs(lua);
luaL_loadfile(lua, "./test.lua");
lua_pcall(lua, 0, 0, 0);
lua_close(lua);
lua脚本
- require用来加载动态库;
- “TestLua”为要加载的动态库名,如c/c++语言的动态库——“TestLua.dll”;
- Lua_Test为测试动态库中的函数;
- unrequire用来销毁库;
-- test.lua
-- 库销毁函数
function unrequire(m)
for key, _ in pairs(package.preload) do
if string.find(tostring(key), m) == 1 then
package.preload[key] = nil
end
end
for key, _ in pairs(package.loaded) do
if string.find(tostring(key), m) == 1 then
package.loaded[key] = nil
end
end
end
-- 加载测试库
m = require('TestLua')
-- 调用库函数
Lua_Test();
-- 销毁测试库
unrequire("TestLua")
待测动态库
待测动态库是对待测接口简单的再封装,便于lua脚本调用。
命令要求:
- 测试动态库的对外接口必须以“luaopen__测试库名称”格式命名;_
- 测试动态库内部的接口定义尽量定义为“Lua_待测试接口的名称”,便于格式统一;
// test.cpp
// 待测试函数
static int Lua_Test(lua_State* lua)
{
lua_getglobal(lua, "Add");
lua_pushnumber(lua, 100);
lua_pushnumber(lua, 200);
lua_call(lua, 2, 1);
return 1;
}
// 统一入口函数
TEST_LUA_API int luaopen_TestLua(lua_State* lua)
{
// 函数注册
lua_register(lua, "Lua_Test", Lua_Test);
return 0;
}