C++向Lua传递二维数组或向量

刚刚整理了C++向Lua通过表的方式传递一维数组或向量,这篇继续补充C++如何通过表的方式向Lua传递二维数组或向量。

在上例程之前,先介绍一下关键函数lua_settable()的工作机理:

void lua_settable (lua_State *L, int index);

英文释义:Does the equivalent to t[k] = v, where t is the value at the given index, v is the value at the top of the stack, and k is the value just below the top. This function pops both the key and the value from the stack. As in Lua, this function may trigger a metamethod for the "newindex" event.

意思是说,这个函数的作用呢,等价于设置表的元素t[k] = v,t是要设置的表,k为表中的key值,v为key值对应的value。调用该函数时,保证要设置的value值v在栈顶,而key值k在栈顶下面一个,也就是-2的位置,表在-3的位置。该函数执行完后,会把key值和value值从栈中弹出。

明白了以上原理,操作二维表就会明了很多,其实跟操作一维表是一样的,只不过二维表的value值也是一个表。

画了两个lua_settable()的示意图,分别为操作一维表和二维表的过程,如下:

好了,上个例程:

C++代码:

#include <iostream>
#include <vector>
#include <string>

#include "lua.hpp"

/* 定义一个函数,将一个字符串向量中的内容压入Lua栈,并调用Lua函数对其进行处理 */
int put_2D_array_to_lua(lua_State *L, std::vector<std::vector<std::string> > str_vec)
{
	lua_getglobal(L, "test_table_2D");
	if(!lua_isfunction(L, -1))
	{
		std::cout << "Get Lua function failed!" << std::endl;
		return -1;
	}
	
	lua_newtable(L);
	std::cout << "---1---luaL_typename(L, -1) = " << luaL_typename(L, -1) << std::endl;  //现在table位于栈顶
	std::cout << "---1---luaL_typename(L, -2) = " << luaL_typename(L, -2) << std::endl;  //函数位于-2位置
	
	for(int k = 0; k < str_vec.size(); k++)
	{
		lua_pushinteger(L, k + 1);  //压入主表key值,为1~K的连续整数
		lua_newtable(L);  //创建一个子表
		std::cout << "---2---luaL_typename(L, -1) = " << luaL_typename(L, -1) << std::endl;  //现在table位于栈顶
		std::cout << "---2---luaL_typename(L, -2) = " << luaL_typename(L, -2) << std::endl;  //key值位于栈顶下面,即-2位置
		
		/* 构造主表key值对应的value值,该value值是一个子表 */
		for(int i = 0; i < str_vec[k].size(); i++)
		{
			lua_pushinteger(L, i + 1);   //压入表key值,这里是1~n的整数
			lua_pushstring(L, str_vec[k][i].c_str());  // 压入key对应的value值
			lua_settable(L, -3);  //此时表位于-3
			std::cout << "---3---luaL_typename(L, -1) = " << luaL_typename(L, -1) << std::endl;  //sub table
			std::cout << "---3---luaL_typename(L, -2) = " << luaL_typename(L, -2) << std::endl;  // sub table index
			std::cout << "---3---luaL_typename(L, -3) = " << luaL_typename(L, -3) << std::endl;  //main table
		}
			
		lua_settable(L, -3);   //主表位于-3	
		
		std::cout << "---5---luaL_typename(L, -1) = " << luaL_typename(L, -1) << std::endl;  //主表
		std::cout << "---5---luaL_typename(L, -2) = " << luaL_typename(L, -2) << std::endl;  //函数
		std::cout << "---5---luaL_typename(L, -3) = " << luaL_typename(L, -3) << std::endl;	  //空
	}
		
	lua_pcall(L, 1, 1, 0);   //调用名为“test_table”的lua函数
	int result = lua_tointeger(L, -1);   //在栈顶读取函数的返回结果
	
	std::cout << "result = " << result << std::endl;
	
	lua_pop(L, 1);   //将函数出栈
	
	return result;
}

/* 初始化函数 */
lua_State* script_initialize(const char* script_name)
{
	lua_State *pLua = luaL_newstate(); //创建一个Lua虚拟机
	if(!pLua)
	{
		std::cout << "Failed to open Lua!" << std::endl;
		return NULL;
	}
	 
	luaL_openlibs(pLua);  //将标准类库加载到Lua虚拟机
 
	luaL_dofile(pLua, script_name);   //加载并运行lua文件
 
	return pLua;
}


int main()
{
	std::vector<std::string> strs = {"My", "name", "is", "Lua"};
	std::vector<std::vector<std::string> > strs_vec = {{"My", "name","is", "Lua"}, {"Hello", "Lua"}, {"I", "am", "C++"}};
	
	lua_State* pL = script_initialize("table_test.lua");
	if(!pL)
	{
		std::cout << "Error initialize lua state!" << std::endl;
		exit(1);
	}
	
	//int num = put_array_to_lua(pL, strs);
	//std::cout << "After lua call, table element num is " << num << std::endl;
	int num = put_2D_array_to_lua(pL, strs_vec);
	
	lua_close(pL);
	
	return 0;
}

lua脚本:

function test_table_2D(mytable)
	local table_len = #mytable   --获取表长度
	print("table size: ", table_len)    --打印表长度
	
	for idx, subtbl in pairs(mytable) do
		print("sub table size: ", #subtbl)    --打印子表长度
		
		for k, v in pairs(subtbl) do  --打印子表中的元素
		print(v)
		end
	end
	
	return table_len    --返回表长度

end

运行结果:左侧为C++输出,右侧为lua输出。

        

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值