C++中使用lua脚本

还是因为项目的原因,需要在C++中使用到lua脚本,使用到的就是普通的lua库,可以在这里下载。

1. 项目中导入lua模块

创建工程后,在项目中导入lua模块,一个是lua的头文件,还有就是lua的lib库,在项目中包含include和lib路径并设置lib名称即可使用。
在这里插入图片描述
在这里插入图片描述
关于lib库,比较简单的使用方式就是直接使用这个以-static结尾的静态库即可,比较方便,无需其他操作。

2. 使用

先创建一个lua脚本,比较简单,就定义了一个字符串、一个表格、两个函数(一个有参,一个无参)。如下:

mystr = "I'm lua"

myTable = {name = "xiaomign", id = 123456}

function print_hello()
	print("hello lua")
end

function _add(a, b)
	return a + b
end

至于更细致的lua语法,这里就不多加介绍了,在lua官网上有详细的介绍。

使用上比较简单,先附上一段代码:

#include <iostream>
#include <string>

#include "lua/lua.hpp"

using namespace std;

int main(int argc, char *argv[])
{
	///< 创建lua句柄并初始化
	lua_State *pState = luaL_newstate();

	if (nullptr == pState)
	{
		cout << "Lua 初始化失败" << endl;
		return -1;
	}

	///< 加载相关库文件
	luaL_openlibs(pState);

	///< 加载lua文件
	if (luaL_loadfile(pState, "./test.lua"))
	{
		cout << "Lua 文件加载失败" << endl;
	}
	else
	{
		///< 执行lua文件
		if (lua_pcall(pState, 0, 0, 0))
		{
			cerr << lua_tostring(pState, -1) << endl;
		}
		else
		{
			///< 获取值
			lua_getglobal(pState, "mystr");

			string str = lua_tostring(pState, -1);
			cout << str << endl;

			///< 获取表中数据
			lua_getglobal(pState, "myTable");
			lua_getfield(pState, -1, "name");
			cout << lua_tostring(pState, -1) << endl;

			lua_getglobal(pState, "myTable");
			lua_getfield(pState, -1, "id");
			cout << lua_tonumber(pState, -1) << endl;

			///< 调用函数
			lua_getglobal(pState, "print_hello");
			lua_pcall(pState, 0, 0, 0);

			///< 调用计算函数
			lua_getglobal(pState, "_add");
			lua_pushnumber(pState, 10);
			lua_pushnumber(pState, 20);

			if (lua_pcall(pState, 2, 1, 0))
			{
				cout << lua_tostring(pState, -1) << endl;
				lua_close(pState);
			}
			else
			{
				if (lua_isnumber(pState, -1))
				{
					cout << lua_tonumber(pState, -1) << endl;
				}
			}
		}
	}

	lua_close(pState);

	system("pause");

	return 0;
}

2.1 创建lua句柄

使用lua的第一步就是创建一个用于lua和C++之家通信的句柄。
这个句柄极为重要,后面所有涉及到lua的操作,均需要使用到这个句柄

lua_State *pState = luaL_newstate();

只要返回的pState不是nullptr,就说明创建句柄成功。

2.2 加载lua的相关库

创建完句柄之后,需要加载lua的库文件,这一点和socket编程有点类似。

luaL_openlibs(pState);

2.3 加载lua文件

luaL_loadfile(pState, "./test.lua")

luaL_loadfile是一个宏,其原型为:

#define luaL_loadfile(L,f)	luaL_loadfilex(L,f,NULL)

加载成功的话,返回值是0.

2.4 执行lua文件

执行的意思,可以理解为激活,就是说如果这个句柄处于激活状态,就可以顺利地执行相关的操作。

lua_pcall(pState, 0, 0, 0)

这玩意也是一个宏值,如下:

#define lua_pcall(L,n,r,f)	lua_pcallk(L, (n), (r), (f), 0, NULL)

这个函数参数的含义如下:

1. 参数1:lua句柄
2. 参数2:参数个数
3. 参数3:返回值个数
4. 参数4:错误处理函数,0表示无,表示错误处理函数在栈中的索引

执行成功的话,返回值为0.

至此,前期准备工作结束,接下来就是对于lua脚本内部东西进行的处理了,如下方介绍。

2.5 正式操作lua脚本

2.5.1 获取值

获取值比较简单,因为在lua脚本中定义了一个名为mystr的变量,因此,这里面就可以使用lua_getglobal函数,通过“mystr”名字的方式,获得这个字符串。

lua_getglobal(pState, "mystr");

因为已知这玩意是个字符串,因此可以采用lua_tostring这个宏将其转化为字符串类型(返回的是C++中的string类)。

string str = lua_tostring(pState, -1);
cout << str << endl;

lua_tostring宏值原型如下:

#define lua_tostring(L,i)	lua_tolstring(L, (i), NULL)

2.5.2 获取表值

接下来是获取表值,因为定义了一个表,名为“myTable”,有两个键值对,分别为“name”和“id”,操作如下。
首先取出表:

lua_getglobal(pState, "myTable");

然后取出表中值:

lua_getfield(pState, -1, "name");
cout << lua_tostring(pState, -1) << endl;

不过有一点值得注意,每次加载表格只能获取其中一个值,如果想要获取第二个值,需要重新加载表格

lua_getglobal(pState, "myTable");
lua_getfield(pState, -1, "name");
cout << lua_tostring(pState, -1) << endl;

lua_getglobal(pState, "myTable");
lua_getfield(pState, -1, "id");
cout << lua_tonumber(pState, -1) << endl;

2.5.3 调用函数

函数可以分为有参函数和无参函数两种,下面进行介绍。

2.5.3.1 无参函数

无参函数比较简单,直接通过函数名获得函数,然后调用lua_pcall调用即可。

lua_getglobal(pState, "print_hello");
lua_pcall(pState, 0, 0, 0);
2.5.3.2 有参函数

无参函数相对来说要麻烦一些,需要先将参数传进去,然后再调用。

lua_getglobal(pState, "_add");
lua_pushnumber(pState, 10);///< 压入参数1
lua_pushnumber(pState, 20);///< 压入参数2

if (lua_pcall(pState, 2, 1, 0))
{
	///< 调用失败
	cout << lua_tostring(pState, -1) << endl;
	lua_close(pState);
}
else
{
	///< 调用成功后获得数据
	if (lua_isnumber(pState, -1))
	{
		cout << lua_tonumber(pState, -1) << endl;
	}
}

2.6 关闭句柄

在调用结束之后,需要关闭句柄,这一步的目的是卸载加载的库,以及安全释放lua句柄。

lua_close(pState);

3. 结果演示

在这里插入图片描述

4. C++调用lua的本质

C++和lua通信的本质是通过一个“虚拟栈”进行交互。

-1表示栈顶,1表示栈底

lua和c++是通过一个虚拟栈来交互的。
c++调用lua实际上是:由c++先把数据放入栈中,由lua去栈中取数据,然后返回数据对应的值到栈顶,再由栈顶返回c++。
lua调c++也一样:先编写自己的c模块,然后注册函数到lua解释器中,然后由lua去调用这个模块的函数。
在lua中,lua堆栈就是一个struct,堆栈索引的方式可是是正数也可以是负数,区别是:正数索引1永远表示栈底,负数索引-1永远表示栈顶

参考链接

lua的一些API
C++调用lua示例
lua5.3语法介绍
lua_pcall函数介绍

  • 11
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值