概述
前面的Lua与C交互之函数注册中讲述了怎么将C函数注册到Lua中让Lua使用。
当Lua中调用C提供的获取数据的接口时,C怎么将多个结构体类型转换成Lua的嵌套table类型呢?
下面通过一个例子来讲解
例子详解
C数据类型
typedef struct student
{
int age; ///< 年龄
int grade; ///< 年级
char name[32]; ///< 姓名
}student;
typedef struct school
{
char phone[32]; ///< 电话
int totalPeople; ///< 总人数
}school;
定义获取数据的接口
int get_student_info(student* p_student)
{
assert(NULL != p_student);
p_student->age = 8;
p_student->grade = 3;
strncpy(p_student->name, "XiaoMing", 32);
return 0;
}
int get_school_info(school* p_school)
{
assert(NULL != p_school);
p_school->totalPeople = 500;
strncpy(p_school->phone, "1008611", 32);
return 0;
}
注册到Lua调用的接口实现
#define JL_GET_ARRAY_MAX 16 ///< 一次获取最多属性数目
#define JL_KEY_BUF_MAX 16 ///< 关键字最大缓存长度
static void format_student(lua_State *L)
{
student student_info;
memset(&student_info, 0, sizeof(student_info));
int ret = get_student_info(&student_info);
if (0 != ret)
{
assert(false);
}
else
{
lua_newtable(L);
lua_pushstring(L, student_info.name);
lua_setfield(L, -2, "name");
lua_pushinteger(L, student_info.age);
lua_setfield(L, -2, "age");
lua_pushinteger(L, student_info.grade);
lua_setfield(L, -2, "grade");
//嵌套student表到参数表中
lua_pushstring(L, "student");
lua_insert(L, -2); /* student table */
lua_settable(L, -3); /* param.student = student */
}
}
static void format_school(lua_State *L)
{
school school_info;
memset(&school_info, 0, sizeof(school_info));
int ret = get_school_info(&school_info);
if (0 != ret)
{
assert(false);
}
else
{
lua_newtable(L);
lua_pushstring(L, school_info.phone);
lua_setfield(L, -2, "phone");
lua_pushinteger(L, school_info.totalPeople);
lua_setfield(L, -2, "totalPeople");
//嵌套school表到参数表中
lua_pushstring(L, "school");
lua_insert(L, -2); /* school table */
lua_settable(L, -3); /* param.school = school */
}
}
//这里我们注册到Lua的函数 参数为数组{"school", "student"}
int lua_get_info(lua_State *L)
{
luaL_checktype(L, 1, LUA_TTABLE); //检测传递过来的是否为table
int array_len = lua_rawlen(L, 1); //数组的长度
char keys[JL_GET_ARRAY_MAX][JL_KEY_BUF_MAX] = { 0 };
int len_max = (array_len <= JL_GET_ARRAY_MAX) ? array_len : JL_GET_ARRAY_MAX;
int idx = 1;
int keys_num = 0;
//取元素
for (int i = 0; i < len_max; i++)
{
lua_rawgeti(L, 1, idx++); //取数据元素
size_t tmp_len = 0;
const char* p_str = luaL_checklstring(L, -1, &tmp_len);
if ((0 < tmp_len) && (tmp_len < JL_KEY_BUF_MAX))
{
strcpy(keys[keys_num], p_str);
keys_num += 1;
}
lua_pop(L, 1);
}
//返回table
lua_newtable(L);
for (int k = 0; k < keys_num; ++k)
{
if (0 == strcmp(keys[k], "school"))
{
format_school(L); //拼school table
}
else if (0 == strcmp(keys[k], "student"))
{
format_student(L); //拼student table
}
}
return 1; //表明返回一个参数
}
Lua中测试代码
local b_app_api = require(app_api)
local param = b_app_api.get_info{"school", "student"}
assert(param ~= nil)
print(param.student.age, param.student.grade, param.student.name)
print(param.school.phone, param.school.totalPeople)
结果:
[LUA-print]: 8 3 XiaoMing
[LUA-print]: 1008611 500
数据数据传递简单实例
1给Lua传递数据
int num_list[] = {2, 5, 8, 3};
lua_newtable(L);
for (int i = 0; i < 4; ++i)
{
lua_pushinteger(L, num[i]);
lua_rawseti(L, -2, i + 1);
}
lua_pushstring(L, "num_list");
lua_insert(L, -2);
lua_settable(L, -3);
2从Lua取数组数据
luaL_checktype(L, 1, LUA_TTABLE);
int array_len = lua_rawlen(L, 1);
int *num_list = new int[array_len];
memset(num_list, 0, sizeof(int) * array_len);
for (int i = 0; i < array_len; ++i)
{
lua_rawgeti(L, 1, i + 1);
num_list[i] = lua_tointeger(L, -1);
lua_pop(L, 1);
}
//To do
delete [] num_list;