简介

Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。

特点

  • 轻量级: 它用标准C语言编写并以源代码形式开放,编译后仅仅一百余K,可以很方便的嵌入别的程序里。
  • 可扩展: Lua提供了非常易于使用的扩展接口和机制:由宿主语言(通常是C或C++)提供这些功能,Lua可以使用它们,就像是本来就内置的功能一样。
  • 其它特性
  • 支持面向过程(procedure-oriented)编程和函数式编程(functional programming);
  • 自动内存管理;只提供了一种通用类型的表(table),用它可以实现数组,哈希表,集合,对象;
  • 语言内置模式匹配;闭包(closure);函数也可以看做一个值;提供多线程(协同进程,并非操作系统所支持的线程)支持;
  • 通过闭包和table可以很方便地支持面向对象编程所需要的一些关键机制,比如数据抽象,虚函数,继承和重载等。

实例

实验目的

使用lua脚本调用c动态库接口。

lua解释器

流程分析

lua解释器的流程:

  • 预读lua脚本文件,将脚本中信息入栈(函数映射、语法映射);
  • 函数调用时逐一出栈;
核心:数据交换。lua的一切运算都是在堆栈上完成的,这个堆栈使lua与c/c++等语言交换数据的手段。

处理流程如下图所示:

Xlua调用DOFade_开发语言

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;
}