LUA-C++交互篇-lua与c++数据传输栈分析

1.lua向c++数据传输过程分析

本部分,我们将会通过图示+代码的方式解读数据的存储结构

1.1 基本数据存储结构

众所周知的,lua常用的数据类型包括:table,number,string
所以,基本数据就为:number,string,复合数据:table

1.2 定义:lua向c++传输数据过程

lua向c传递数据,通过的是栈,这一点毋庸置疑,lua向c++传输数据我们定义为:
1. 一个由c++编写的用来给lua调用的模块,定义为core
2. 当在lua中调用core.xxx(a,b,c)时,我们称从lua将数据传递给了c++

1.3 基本数据类型的数据传输过程

1.3.1 luaToC++测试代码

local core = require("LuaShare")
local v2 = core.setPos(1.1,2.2,3.3);

1.3.2 c++接收数据时,我们讨论的问题

  • 数据存储在栈中的的位置?或者数据的表现形式?
  • 对于luaL_checknumber(L,1)的数据获取方式
  • 对于luaL_checknumber(L,-1)的数据获取方式

a.数据存储在栈中的的位置?或者数据的表现形式?

在这里插入图片描述

b.对于luaL_checknumber(L,1)的数据获取方式

在c++中,我们要获取传过来的Lua参数,通常会这样

static int setPos(lua_State* L) {
	double l1 = luaL_checknumber(L, 1);
}

我们尝试打印这个数据:
在这里插入图片描述
很容易的得出结论:
luaL_checknumber(L,1)中的1,指从栈底开始获取数据,就像这种:
在这里插入图片描述

c. 对于luaL_checknumber(L,-1)的数据获取方式
static int setPos(lua_State* L) {
double l1 = luaL_checknumber(L, -1);
cout << setw(5) << l1 << endl;

结果输出
在这里插入图片描述
很自然的,我们可以推断:
在这里插入图片描述

1.4 table类型数据的传输过程

当我们开始涉足到table的传输,一切都看起来变得非常复杂了...

1.4.1 一个简单的table传输

lua代码:

local core = require("LuaShare")
local vec3 = {x = 1.1,y = 2.2,z = 3.3}
core.setPos(vec3);

现在,我们尝试研究几个问题:

  • 此时的虚拟栈中栈的长度是多少?
  • 我们怎么捕捉(遍历)这个table的数据?
  • 当table类型和number类型及其string类型混合传入时,怎么拆解?
a. 虚拟栈中栈的长度是多少?

你可以使用函数:lua_gettop(lua_State *L);去捕捉这个长度

static int setPos(lua_State* L) {
	
	int len = lua_gettop(L);

	cout <<"长度为:"<< len << endl;
	
	return 0;
}

输出结果:
在这里插入图片描述
显然,一个table仅占一个坑位

b.怎么去获取(遍历)这个table呢?

方法很简单,将你要访问的table放到栈底就行
如果你只有一个table:

local core = require("LuaShare")
local vec3 = {x = 1.1,y = 2.2,z = 3.3}
local vec4 = {x = 3.1,y =4.2,z = 5.3}
core.setPos(vec3);
typedef unordered_map<string, double> sdmap;
static sdmap checkTable(lua_State *L) {
	lua_pushnil(L);
	sdmap sdp;
	while (lua_next(L, 1) != 0)
	{
		sdp.insert({ lua_tostring(L, -2) , lua_tonumber(L, -1) });
		lua_pop(L,1);
	}
	lua_remove(L, 1);//将栈底移除
	return sdp;
}
//测试代码:
static int setPos(lua_State* L) {
	sdmap mp = checkTable(L);
	print(mp);
}

结果输出:
在这里插入图片描述
如果你存在两个以上的table:

local core = require("LuaShare")
local vec3 = {x = 1.1,y = 2.2,z = 3.3}
local vec4 = {x = 3.1,y =4.2,z = 5.3}
core.setPos(vec3,vec4);

在c++中解析也很方便:

static int setPos(lua_State* L) {
	sdmap mp = checkTable(L);
	print(mp);	
	sdmap mpmp = checkTable(L);
	print(mpmp);
	return 0;
}

结果输出:
在这里插入图片描述
如果你同时包括参数和table,建议将table放在栈底(lua的第一个参数),或者在check_number(L,1)后,手动lua_remove(L,1),这个时候table就会放到栈底:

local core = require("LuaShare")
local vec3 = {x = 1.1,y = 2.2,z = 3.3}
local vec4 = {x = 3.1,y =4.2,z = 5.3}
core.setPos("lostArea",vec4);
static int setPos(lua_State* L) {
	string db = luaL_checkstring(L, 1);
	lua_remove(L, 1);
	cout << "check ans = " << db << endl;
	sdmap mpmp = checkTable(L);
	print(mpmp);

结果输出:
在这里插入图片描述

1.5 常见的对数据栈的操作函数

1.5.1 lua_pushnumber(L, 123);

这个函数我们很容易的确定,就是将数据从栈顶压入到栈底,我们接下来进行测试
1. 我们通过该函数压入两个数123,233到数据栈中
2. 我们在lua中用local a,b去接收这两个数
请猜测:
	a = 123还是233?

c++代码:

static int setPos(lua_State* L) {
	
	lua_pushnumber(L, 123);
	lua_pushnumber(L, 233);
	return 2;//返回的参数数量
}

lua代码:

local core = require("LuaShare")
local a,b = core.setPos()
print(a)
print(b)

测试结果:
在这里插入图片描述
我们可以得出结论:
返回的数据顺序是一个队列的这样一个顺序:先进先出
类似操作的函数还有

lua_pushnil(lua_State*);
lua_pushboolean(lua_State*, bool);
lua_pushnumber(lua_State*, lua_Number);
lua_pushinteger(lua_State*, lua_Integer)
lua_pushlstring(lua_State*, const char*, size_t);
lua_pushstring(lua_State*, const char*);
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值