Skip to content

在C中调用Lua代码 ​

在C中调用Lua代码走的是 Lua C API:执行Lua脚本、调用Lua函数、处理返回值,全都围绕一个 lua_State 和它的栈进行。

1. 初始化Lua环境 ​

所有操作都基于一个Lua状态(lua_State),第一步是创建它。

c
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>

int main() {
    lua_State *L = luaL_newstate();  // 创建新的Lua状态
    luaL_openlibs(L);                // 打开Lua标准库

    // 在这里编写代码...

    lua_close(L);                    // 关闭Lua状态
    return 0;
}

luaL_newstate 创建状态,luaL_openlibs 加载Lua标准库,退出前用 lua_close 关闭状态、释放资源。

2. 加载和执行Lua脚本 ​

代码可以来自文件,也可以来自字符串,各有对应的入口。

从文件加载:

c
if (luaL_dofile(L, "script.lua") != LUA_OK) {
    fprintf(stderr, "Error: %s\n", lua_tostring(L, -1));
    lua_pop(L, 1);  // 处理错误
}

从字符串加载:

c
const char *lua_code = "print('Hello from Lua!')";
if (luaL_dostring(L, lua_code) != LUA_OK) {
    fprintf(stderr, "Error: %s\n", lua_tostring(L, -1));
    lua_pop(L, 1);  // 处理错误
}

两个入口对应两种来源:luaL_dofile 读文件,luaL_dostring 执行字符串。失败时栈顶放着错误信息,用 lua_tostring(L, -1) 取出来。

3. 调用Lua函数 ​

调用分三步:把函数推到栈上,压参数,调用之后取返回值。

c
// 调用Lua函数
lua_getglobal(L, "my_function");  // 获取Lua全局函数
lua_pushnumber(L, 10);            // 推送参数1
lua_pushnumber(L, 20);            // 推送参数2

if (lua_pcall(L, 2, 1, 0) != LUA_OK) {
    fprintf(stderr, "Error: %s\n", lua_tostring(L, -1));
    lua_pop(L, 1);  // 处理错误
} else {
    double result = lua_tonumber(L, -1);  // 获取返回值
    printf("Result: %f\n", result);
    lua_pop(L, 1);  // 清理栈
}

lua_getglobal 把全局函数推上栈,lua_pushnumber 压参数,lua_pcall 发起调用并接收返回值,lua_tonumber 从栈中取出结果。

4. 处理Lua表和函数 ​

函数也可能是某个表的字段。取表、再从表里取函数,调用方式不变。

c
// 调用Lua表中的函数
lua_getglobal(L, "my_table");      // 获取Lua表
lua_getfield(L, -1, "my_function"); // 获取表中的函数
lua_pushnumber(L, 10);            // 推送参数

if (lua_pcall(L, 1, 1, 0) != LUA_OK) {
    fprintf(stderr, "Error: %s\n", lua_tostring(L, -1));
    lua_pop(L, 1);  // 处理错误
} else {
    double result = lua_tonumber(L, -1);  // 获取返回值
    printf("Result: %f\n", result);
    lua_pop(L, 1);  // 清理栈
}

和上一段的区别只在取函数这一步:lua_getfield 从栈顶的表里取字段(这里是函数),而不是从全局环境取。

5. 清理和关闭 ​

用完之后,lua_close 关闭Lua状态并释放资源:

c
lua_close(L);  // 关闭Lua状态

Hello Lua