1. 背景
本文主要介绍在c++中如何嵌入lua脚本进行基本使用,这里的测试环境主要是centos,所以去lua官网下载对应的lua二进制库LuaBinaries - Browse /5.4.2/Linux Libraries at SourceForge.net
注:注意lua的二进制库不同版本可能需要不同的glibc库的支持,即对应的gcc编译器版本可能不一样,选择下载对应的lua版本即可
2. Lua 基本概要
Lua 是一种轻量级的、高效、可嵌入的脚本编程语言,设计初衷是为了作为一种配置语言,以便为应用程序提供灵活的扩展机制。随着时间发展,Lua 也广泛应用于游戏开发、嵌入式系统、服务器管理工具、脚本编程等多个领域, 详细介绍可以查看官网介绍 Lua: about
3. Lua的主要特点以及使用场景
关键特点:
- 轻量级:Lua 体积小,运行时环境占用资源少,适合资源受限的环境。
- 简洁的语法:Lua 的设计哲学是“少即是多”,其语法简单直观,易于学习。
- 可嵌入性:Lua 可轻松嵌入到宿主程序中,提供强大的扩展能力,而不会显著增加宿主程序的复杂度。
- 自动内存管理:Lua 使用垃圾回收器自动管理内存,减轻了程序员的负担。
- 动态类型系统:Lua 是动态类型的,变量的类型可以在运行时改变。
- 支持面向过程和面向对象编程:虽然Lua本身不强制任何特定的编程范式,但它提供了足够的机制来支持过程化编程以及基于表的面向对象编程。
- 协程:Lua 支持协程,这是一种比线程更轻量级的并发机制,适合编写高效率的异步代码。
- 标准库:Lua 提供了一个小巧但功能全面的标准库,包括字符串处理、表操作、I/O、数学运算等。
应用场景:
- 游戏开发:Lua 因其轻量级和高效性,常被用于游戏开发中编写游戏逻辑、脚本和MOD。
- 嵌入式系统:在资源有限的设备上,Lua 作为配置和控制语言使用。
- Web服务器:部分Web服务器和框架使用Lua来处理请求,实现动态内容生成。
- 自动化和工具脚本:Lua 也常用于构建系统管理脚本和自动化工具。
- 扩展和插件系统:许多应用程序(如Adobe Lightroom、Wireshark)使用Lua作为其扩展语言。
4. Lua如何嵌入到c++中进行使用呢?以下通过基本的函数调用及函数注册来进行说明
在c++代码里执行lua代码,请看下面的例子
<test.lua>
function sub(a, b)
return a-b
end
<main.cpp>
#include <iostream>
#include <stdio.h>
#include <thread>
#include <pthread.h>
#include "./include/lua.hpp"
int main(int argc, char** argv)
{
// 创建一个新的lua状态机环境
lua_State* L = luaL_newstate();
// 在已经创建的Lua虚拟机(lua_State)中打开并注册Lua的标准库
luaL_openlibs(L);
// 加载lua脚本到状态机
luaL_dofile(L, "./test.lua");
// 从状态机中读取lua中的函数
lua_getglobal(L, "sub");
// 将参数1压入栈
lua_pushnumber(L, 10);
// 将参数2压入栈
lua_pushnumber(L, 2);
// 调用lua函数, 2表示参数个数, 1表示函数返回值个数
lua_call(L, 2, 1);
// 因为函数调用完毕之后函数结果会存储在栈顶的位置,默认栈顶索引为-1
int sub_result = lua_tonumber(L, -1);
// 打印调用结果
fprintf(stdout, "thread: %llu, sub result: %d\n", pthread_self(), sub_result);
}
编译命令:g++ -std=c++11 -g -o main main.cpp -L./ -llua54 -ldl -lpthread -Wl,--rpath=/home/juncai/Desktop/Myproject/Lua
编译将c++嵌入到lua中执行,参见如下代码
#include <iostream>
#include <stdio.h>
#include <thread>
#include <pthread.h>
#include "./include/lua.hpp"
// 自定义函数用于注册给lua调用
extern "C" int my_sum(lua_State* L)
{
int num1 = lua_tonumber(L, 1);
int num2 = lua_tonumber(L, 2);
int result = num1 + num2;
uint64_t this_thread = pthread_self();
fprintf(stdout, "args 1: %d\n", num1);
fprintf(stdout, "args 2: %d\n", num2);
fprintf(stdout, "thread: %llu, call sum result: %d\n", this_thread, result);
// push stack
lua_pushnumber(L, result);
return result;
}
int main(int argc, char** argv)
{
// 创建一个新的lua状态机环境
lua_State* L = luaL_newstate();
// 在已经创建的Lua虚拟机(lua_State)中打开并注册Lua的标准库
luaL_openlibs(L);
// 注册函数给lua的状态机
lua_pushcfunction(L, my_sum);
lua_setglobal(L, "my_sum");
// 加载并执行Lua脚本
if (luaL_dostring(L, "my_sum(10, 20)")) {
// 如果执行出错,打印错误信息
fprintf(stderr, "%s", lua_tostring(L, -1));
lua_pop(L, 1); // 移除错误信息
}
lua_close(L); // 关闭Lua状态机,释放资源
}