LUA和C/C++交互
更新时间: 2026/02/09
在Gitcode上查看源码LUA和C/C++交互
Lua和C/C++之间通信的主要主件是无处不在的虚拟栈,几乎所有的API调用都是操作这个栈中的值。
C/C++调用lua(表现Lua的嵌入式)
lua_pcall 是 Lua C API 中的一个函数,用于以保护模式调用 Lua 函数。在调用 Lua 函数时,如果发生了错误,lua_pcall 会捕获这个错误并返回错误码,而不会让程序直接崩溃。
‘int lua_pcall(lua_State *L, int nargs, int nresults, int errfunc);’
- lua_State *L 是表示 Lua 解释器状态的指针。
- int nargs 是传递给 Lua 函数的参数个数。
- int nresults 是期望从 Lua 函数中返回的结果个数。
- int errfunc 是错误处理函数在栈中的索引(通常为 0 表示使用默认的错误处理函数)。
lua_pcall 的返回值是执行结果,如果执行成功返回 0,如果有错误则返回其他值,并且错误信息会被压入栈顶。
在调用lua_call函数之前,需要将函数本身和所有的参数依次压入Lua栈中。但是,对于栈上的元素来说,索引是从1开始的,而不是从0开始。所以,在lua_call函数中,第一个索引位置对应的是被调用的函数,而不是第二个1的索引位置。第二个1索引位置对应的是该函数的第一个参数。 举个例子,如果你有一个函数在Lua中定义为:
lua
function my_function(x, y)
return x + y
end在C中调用:
C
#include <lua.hpp>
#include <stdio.h>
int main() {
lua_State* L = luaL_newstate();
luaL_openlibs(L);
// 加载和执行 Lua 脚本文件的步骤...
lua_getglobal(L, "my_function"); // 将函数本身推入栈
lua_pushinteger(L, 1); // 将参数 x 推入栈
lua_pushinteger(L, 2); // 将参数 y 推入栈
lua_pcall(L, 2, 1, 0); // 调用函数,传入2个参数,期望返回1个结果
// 获取返回值
if (lua_isinteger(L, -1)) {
int result = lua_tointeger(L, -1);
printf("Result of my_function: %d\n", result);
} else {
printf("Error: result is not an integer.\n");
}
lua_pop(L, 1); // 弹出返回值
lua_close(L);
return 0;
}lua调用C/C++(表现Lua的可扩展性)
- lua不可以调用所有C函数,只能调用遵循某种规则定义的C函数,lua调C时必须注册该函数,即以一种恰当的方式为lua提供c函数的地址。
- lua调用C函数时,也使用了与C调用lua时相同类型的栈,C从栈中获取参数,并将结果压入栈中。但是这个栈不是全局结构,每一个函数都有其私有的局部栈。当lua调用C函数,第一个参数总是位于索引位置为1的位置。
C函数定义:
C
static int l_sin(lua_State *L){
double d = luaL_checknumber(L, 1); // 从虚拟栈中取出参数
double res = sin(d); // 调用c/c++函数计算
lua_pushnumber(L, res); // 将结果压入虚栈
return 1; // 返回返回值个数
}第一种调用方式:简单的独立解释器调用
C
c代码:
#include <stdio.h>
#include <string.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#include <math.h>
static int l_sin(lua_State *L){
double d = luaL_checknumber(L, 1); // 从虚拟栈中取出参数
double res = asin(d); // 调用c/c++函数计算
lua_pushnumber(L, res); // 将结果压入虚栈
return 1; // 返回返回值个数
}
int main(void){
char buff[256];
int error;
lua_State *L=luaL_newstate();
luaL_openlibs(L);
lua_pushcfunction(L, l_sin);
lua_setglobal(L, "mysin");
error = luaL_dofile(L, "271.lua"); // Execute the Lua script file
if (error) {
fprintf(stderr, "Error executing script: %s\n", lua_tostring(L, -1));
lua_pop(L, 1); // Pop the error message from the stack
}
lua_close(L);
return 0;
}
lua调用脚本271.lua:
local angle = 0.5
local result = mysin(angle)
print("sin(" .. angle .. ") =", result)
注:其中lua脚本的路径是相对于执行时的路径。第二种调用方式:将c函数注册到Lua环境中,作为库函数。把c函数编译成动态库,链接到lua环境中
C
库函数注册:
#include <stdio.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include <math.h>
static int l_sin(lua_State *L){
double d = luaL_checknumber(L, 1); // 从虚拟栈中取出参数
double res = sin(d); // 调用c/c++函数计算
lua_pushnumber(L, res); // 将结果压入虚栈
return 1; // 返回返回值个数
}
// 注册 C 函数到 Lua 环境中
static const struct luaL_Reg mylib[] = {
{"l_sin", l_sin}, // 注册函数名为 l_sin
{NULL, NULL} // 结束标记
};
int luaopen_mylib(lua_State *L) {
luaL_newlib(L, mylib); // 创建新的 Lua 库并注册函数
return 1; // 返回创建的 Lua 库
}
lua调用:
local mylib = require("mylib")
print(mylib.l_sin(3.14159))