C/C++ 调用 Lua API 读取脚本变量的完整示例

七月
七月
发布时间:2026-10-14| 3人浏览过
原创

在C/C++开发中嵌入Lua脚本是扩展功能的常用手段。本文演示如何通过Lua API从C端读取Lua脚本定义的全局变量。核心流程包括:创建虚拟机上下文、加载并安全执行脚本、使用lua_getglobal将变量推入虚拟栈、通过lua_tonumber转换为C类型数据,最后正确清理资源。

实现目标与准备条件

本示例的目标是在控制台应用程序(C或C++)中运行一段Lua代码,并准确获取脚本中定义的数值型全局变量rows和cols。读者需确保已配置好Lua的C头文件(如lua.h)及链接库环境。

第1步:编写测试用的 Lua 脚本

目的是定义待读取的全局变量。创建一个名为test01.lua的文件,内容如下:

function plustwo(x)
    local a = 2;
    return x+a;
end;

rows = 6;
cols = plustwo(rows);

该脚本定义了一个辅助函数plustwo,并将结果赋值给全局变量cols。注意Lua中默认未声明局部范围的变量为全局变量。

第2步:配置 C/C++ 项目并引入 Lua 头文件

在IDE(如VS)中新建控制台程序,必须将Lua的C接口头文件包含在extern "C"块中,以避免C++名称修饰问题。

#include <iostream>

extern "C"
{
    #include "lua.h"
    #include "lauxlib.h"
    #include "lualib.h"
}

using namespace std;

第3步:初始化虚拟机并加载脚本

创建Lua状态机(LState),打开标准库,并加载外部脚本文件。此阶段需严格检查加载和编译错误。

int main(int argc, char* argv[])
{
    cout << "01_Read_Stack" << endl;

    /* 创建 Lua VM */
    lua_State *L = lua_open();
    
    /* 打开必要库,根据实际需求选择开启的模块 */
    luaopen_base(L);
    luaopen_table(L);
    luaL_openlibs(L);     /* 打开所有标准库 */
    luaopen_string(L);
    luaopen_math(L);

    int iError;
    /* 加载脚本文件 */
    iError = luaL_loadfile(L, "../test01.lua");
    if (iError)
    {
        cout << "Load script FAILED!" << lua_tostring(L, -1) << endl;
        lua_close(L);
        return 1;
    }

    /* 执行加载后的 chunk */
    iError = lua_pcall(L, 0, 0, 0);
    if (iError)
    {
        cout << "pcall FAILED" << lua_tostring(L, -1) << iError << endl;
        lua_close(L);
        return 1;
    }

    // ... 后续步骤见下文
}

第4步:通过栈操作获取变量值

Lua与C交互基于“栈”。获取全局变量的步骤如下:

  1. 压栈:使用lua_getglobal(L, name)获取栈顶索引。
    • 先调用lua_getglobal(L, "rows")。
    • 再调用lua_getglobal(L, "cols")。
    • 此时栈底在上,栈顶在下。假设栈指针为T,则rows在T-2位置,cols在T-1位置。
  2. 类型校验:使用lua_isnumber()确认数据类型是否符合预期。
  3. 取值:使用lua_tonumber()将数值转换为C的double类型。
    /* 获取全局变量 rows 和 cols 进入栈 */
    lua_getglobal(L, "rows");
    lua_getglobal(L, "cols");

    /* 检查类型是否为数字,负数索引表示相对于栈顶的位置 */
    if (!lua_isnumber(L, -2))
    {
        cout << "[rows] is not a number" << endl;
        lua_close(L);
        return 1;
    }
    if (!lua_isnumber(L, -1))
    {
        cout << "[cols] is not a number" << endl;
        lua_close(L);
        return 1;
    }

    /* 输出结果,使用 static_cast 显式转换精度 */
    cout << "[rows] " 
         << static_cast<int> (lua_tonumber(L, -2)) 
         << "\n[cols] " 
         << static_cast<int> (lua_tonumber(L, -1)) 
         << endl;

第5步:清理栈空间并关闭虚拟机

为避免内存泄漏或栈污染,使用完毕后应弹出使用的栈元素并关闭LState。

    /* 弹出最后两个元素 (rows 和 cols) */
    lua_pop(L, 2);
    
    /* 关闭 Lua VM */
    lua_close(L);
    
    return 0;
}

关键知识点解析

  • 相对索引:-1 代表栈顶元素,-2 代表栈顶之下一个元素。这种设计使得在中间插入或删除元素时,其他元素的索引自动调整,无需手动计算绝对索引。
  • 错误处理:luaL_loadfile负责编译脚本(静态错误),lua_pcall负责执行脚本(运行时错误)。务必对两者返回值进行检查。
  • 库的开启:lua_open仅创建空状态,需要手动luaopen_*来添加功能。生产环境中通常直接使用luaL_newstate配合luaL_openlibs以简化代码。
以上就是在C/C++中通过Lua API访问脚本变量的详细内容,更多关于跨语言交互与Lua集成的资料请关注本站其它相关文章!
相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。