目标
之前的博客《尝试在C++中调用Lua》所做的,相当于是让C++可以“知道”Lua中的东西。
而本篇的目标是相反的调用方向,即让Lua可以“知道”C++里的东西,例如变量和函数。
(环境上接之前的博客《尝试在C++中调用Lua》)
接下来的内容参考了其他人的文章。不过所用的Lua接口都可以在官方的Lua 5.3 Reference Manual中找到权威的解释。
Lua得到C++中的变量
代码参考了《lua与C交互(5):lua调用C变量_心清的专栏-CSDN博客》
添加一个变量到全局中的语法是:
//添加一个字符串型全局变量
{
lua_pushstring(L, "yaksue"); //入栈一个字符串
lua_setglobal(L, "g_testStr"); //将栈顶的数据出栈到lua全局变量区,并且赋给一个变量名"g_testStr"
}
//添加一个整数型局部变量
{
lua_pushinteger(L, 123); //入栈一个整数
lua_setglobal(L, "g_testInt"); //将栈顶的数据出栈到lua全局变量区,并且赋给一个变量名"g_testInt"
}
对于稍微复杂的表:
//添加一个“表”
{
lua_newtable(L); //入栈:新建一个表
{
lua_pushinteger(L, 777); //入栈:一个整数
lua_pushstring(L, "love"); //入栈:一个字符串
lua_setfield(L, 1, "m_Str"); //出栈:将栈顶的数据出栈到"m_Str"字段
lua_setfield(L, 1, "m_Int"); //出栈:将栈顶的数据出栈到"m_Int"字段
}
lua_setglobal(L, "g_testTable"); //出栈,为这个表命名为"g_testTable"
}
最终代码:
#include<iostream>
extern "C"
{
#include "LuaSrc/lua.h"
#include "LuaSrc/lualib.h"
#include "LuaSrc/lauxlib.h"
}
//全局的 Lua state
lua_State* L;
int main(void)
{
//创建一个 Lua state
L = luaL_newstate();
//Opens all standard Lua libraries into the given state.
//对于一个给定的 Lua state 打开所有的Lua标准库
luaL_openlibs(L);
//添加一个字符串型全局变量
{
lua_pushstring(L, "yaksue"); //入栈一个字符串
lua_setglobal(L, "g_testStr"); //将栈顶的数据出栈到lua全局变量区,并且赋给一个变量名"g_testStr"
}
//添加一个整数型局部变量
{
lua_pushinteger(L, 123); //入栈一个整数
lua_setglobal(L, "g_testInt"); //将栈顶的数据出栈到lua全局变量区,并且赋给一个变量名"g_testInt"
}
//添加一个“表”
{
lua_newtable(L); //入栈:新建一个表
{
lua_pushinteger(L, 777); //入栈:一个整数
lua_pushstring(L, "love"); //入栈:一个字符串
lua_setfield(L, 1, "m_Str"); //出栈:将栈顶的数据出栈到"m_Str"字段
lua_setfield(L, 1, "m_Int"); //出栈:将栈顶的数据出栈到"m_Int"字段
}
lua_setglobal(L, "g_testTable"); //出栈,为这个表命名为"g_testTable"
}
//打开Lua脚本文件
luaL_dofile(L, "test2.lua");
//关闭 Lua state
lua_close(L);
return 0;
}
Lua代码:
--打开文件时的测试打印信息
print("Hello Lua File")
print("g_testStr:", g_testStr)
print("g_testInt:", g_testInt)
print("g_testTable.m_Int:", g_testTable.m_Int)
print("g_testTable.m_Str:", g_testTable.m_Str)
输出:
Hello Lua File
g_testStr: yaksue
g_testInt: 123
g_testTable.m_Int: 777
g_testTable.m_Str: love
Lua得到C++中的函数
代码参考了《三、Lua调用C++函数 - 知乎》
C++中的函数是这样,只是简单地将所有的参数累加:
static int MyCppFunction(lua_State* L)
{
//获得当前栈顶有几个元素
int n = lua_gettop(L);
int sum = 0;//准备累加所有的元素
for (int i = 1; i <= n; ++i)
sum += lua_tonumber(L, i);//得到栈顶的第i个元素,转换为数字
//入栈一个元素作为返回结果
lua_pushnumber(L, sum);
//返回压入了几个元素
return 1;
}
随后这样注册:
//注册这个函数
lua_register(L, "MyCppFunction", MyCppFunction);
最终代码:
#include<iostream>
extern "C"
{
#include "LuaSrc/lua.h"
#include "LuaSrc/lualib.h"
#include "LuaSrc/lauxlib.h"
}
//全局的 Lua state
lua_State* L;
static int MyCppFunction(lua_State* L)
{
//获得当前栈顶有几个元素
int n = lua_gettop(L);
int sum = 0;//准备累加所有的元素
for (int i = 1; i <= n; ++i)
sum += lua_tonumber(L, i);//得到栈顶的第i个元素,转换为数字
//入栈一个元素作为返回结果
lua_pushnumber(L, sum);
//返回压入了几个元素
return 1;
}
int main(void)
{
//创建一个 Lua state
L = luaL_newstate();
//Opens all standard Lua libraries into the given state.
//对于一个给定的 Lua state 打开所有的Lua标准库
luaL_openlibs(L);
//注册这个函数
lua_register(L, "MyCppFunction", MyCppFunction);
//打开Lua脚本文件并运行
luaL_dofile(L, "test3.lua");
//关闭 Lua state
lua_close(L);
return 0;
}
Lua代码:
--打开文件时的测试打印信息
print("Hello Lua File")
print(MyCppFunction(3,4,5))
输出:
Hello Lua File
12.0
tip:得到Lua栈当前的大小
Lua中的栈其实还是让我挺迷惑的,因为我不太容易通过函数的名字来明确判断哪个API入栈了,哪个API出栈了。。。
不过可以通过lua_gettop(L)
函数来得到栈的大小,这对于学习比较有帮助。
例如,可以加一些打印的命令穿插在API调用中:
//添加一个“表”
{
std::cout << "栈当前的大小" << lua_gettop(L) << std::endl;//测试打印栈大小
lua_newtable(L); //入栈:新建一个表
std::cout << "栈当前的大小" << lua_gettop(L) << std::endl;//测试打印栈大小
{
lua_pushinteger(L, 777); //入栈:一个整数
std::cout << "栈当前的大小" << lua_gettop(L) << std::endl;//测试打印栈大小
lua_pushstring(L, "love"); //入栈:一个字符串
std::cout << "栈当前的大小" << lua_gettop(L) << std::endl;//测试打印栈大小
lua_setfield(L, 1, "m_Str"); //出栈:将栈顶的数据出栈到"m_Str"字段
std::cout << "栈当前的大小" << lua_gettop(L) << std::endl;//测试打印栈大小
lua_setfield(L, 1, "m_Int"); //出栈:将栈顶的数据出栈到"m_Int"字段
std::cout << "栈当前的大小" << lua_gettop(L) << std::endl;//测试打印栈大小
}
lua_setglobal(L, "g_testTable"); //出栈,为这个表命名为"g_testTable"
std::cout << "栈当前的大小" << lua_gettop(L) << std::endl;//测试打印栈大小
}
这样便可以得到信息:
栈当前的大小0
栈当前的大小1
栈当前的大小2
栈当前的大小3
栈当前的大小2
栈当前的大小1
栈当前的大小0