第8章:C API
一、导读
1.1 本章学习目标
第8章讲解 Lua 的 C API:如何在 C 中嵌入 Lua、如何注册 C 函数给 Lua 调用。
本章核心学习目标:
- 理解 lua_State:Lua 环境的核心
- 掌握栈操作:push、pop、get、set
- 掌握 C 函数注册
- 理解错误处理
1.2 为什么本章如此重要
C API 是 Lua 嵌入和扩展的基础。游戏引擎、高性能库都通过 C API 与 Lua 交互。
1.3 核心问题引导
lua_State 是什么?为什么每个线程需要一个?
Lua 栈如何工作?
如何从 C 调用 Lua 函数?
二、核心概念详解
2.1 lua_State 和栈
c
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
// 创建 Lua 环境
lua_State *L = luaL_newstate();
luaL_openlibs(L); // 打开标准库
// 栈操作
lua_pushnumber(L, 3.14); // 压入数字
lua_pushstring(L, "hello"); // 压入字符串
lua_pushboolean(L, 1); // 压入布尔值
// 获取栈顶元素
double n = lua_tonumber(L, -1);
const char* s = lua_tostring(L, -2);
// 弹出
lua_pop(L, 1);
// 栈大小
int top = lua_gettop(L);
lua_close(L);2.2 注册 C 函数
c
// C 函数签名: int func(lua_State *L)
// 返回值个数
int l_add(lua_State *L) {
double a = luaL_checknumber(L, 1);
double b = luaL_checknumber(L, 2);
lua_pushnumber(L, a + b);
return 1; // 返回 1 个值
}
// 注册到 Lua
lua_pushcfunction(L, l_add);
lua_setglobal(L, "add");
// 在 Lua 中使用:
// print(add(3, 4)) -- 7
// 批量注册
static const luaL_Reg mylib[] = {
{"add", l_add},
{"sub", l_sub},
{"mul", l_mul},
{NULL, NULL}
};
luaL_newlib(L, mylib);
lua_setglobal(L, "mylib");2.3 调用 Lua 函数
c
// 调用 Lua 函数
lua_getglobal(L, "myFunction"); // 获取函数
lua_pushnumber(L, 42); // 参数 1
lua_pushstring(L, "hello"); // 参数 2
// lua_pcall(L, nargs, nresults, errfunc)
int status = lua_pcall(L, 2, 1, 0);
if (status != LUA_OK) {
const char* error = lua_tostring(L, -1);
printf("Error: %s\n", error);
lua_pop(L, 1);
} else {
double result = lua_tonumber(L, -1);
printf("Result: %g\n", result);
lua_pop(L, 1);
}三、实战案例
3.1 案例一:嵌入 Lua 脚本引擎
c
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include <stdio.h>
// C 函数: 打印日志
int l_log(lua_State *L) {
const char* level = luaL_checkstring(L, 1);
const char* msg = luaL_checkstring(L, 2);
printf("[%s] %s\n", level, msg);
return 0;
}
int main() {
lua_State *L = luaL_newstate();
luaL_openlibs(L);
// 注册 C 函数
lua_pushcfunction(L, l_log);
lua_setglobal(L, "log");
// 执行 Lua 脚本
if (luaL_dofile(L, "script.lua") != LUA_OK) {
printf("Error: %s\n", lua_tostring(L, -1));
}
lua_close(L);
return 0;
}
// script.lua:
// log("INFO", "Application started")
// log("DEBUG", "Loading resources...")四、本章小结
lua_State 是 Lua 环境的核心
栈是 C 和 Lua 之间通信的桥梁
C 函数通过栈接收参数和返回值
五、思考与练习
为什么 Lua 使用栈而非直接传参?
如何处理 C 函数中的 Lua 异常?