尝试将C++中变量与函数提供给Lua调用

目标

之前的博客《尝试在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

猜你喜欢

转载自blog.csdn.net/u013412391/article/details/113445916
今日推荐