Lua与C/C++交互
Posted 两片空白
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Lua与C/C++交互相关的知识,希望对你有一定的参考价值。
前言
lua是用C语言实现的,提供了一些列接口来实现和C/C++进行数据的交互。可以查阅lua官网的参考手册。
lua_state 虚拟机
lua_state可以看作是lua的虚拟机,每一个lua虚拟机对应一个lua_state。
lua_state中包含许多变量,其中就包含lua的私有栈和全局表_G。
struct lua_State
CommonHeader;//#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked
lu_byte status;//虚拟机的错误状态码
StkId top;//栈顶元素所在位置的下一个位置,也就是栈上第一个空闲的位置
StkId base;//栈上,当前函数的基址(注意不是函数所在位置)
global_State* l_G;//全局表,环境章节再说
CallInfo* ci;//当前函数调用信息
const Instruction* savedpc;//当前函数的指令位置,指向待取指指令的地址
StkId stack_last;//栈最后一个位置的下一个位置
StkId stack;//寄存器数组的起始位置
CallInfo* end_ci;//函数调用信息数组的最后一个位置的下一个位置
CallInfo* base_ci;//函数调用信息数组首地址
int stacksize;//栈的大小
int size_ci;//函数调用信息数组大小
unsigned short nCcalls;//内嵌C调用层数
unsigned short baseCcalls;//唤醒协程时的内嵌C调用层数
lu_byte hookmask;
lu_byte allowhook;
int basehookcount;
int hookcount;
lua_Hook hook;
TValue l_gt;//Global表
TValue env;//环境表的临时位置
GCObject* openupval;//open状态的upvalues
GCObject* gclist;
struct lua_longjmp* errorJmp;//跳转信息单链表,实现try catch的功能,见函数章节
ptrdiff_t errfunc;//当前错误处理函数在栈上的索引
;
在C/C++中调用lua函数
C/C++调用全局函数
C函数
#include <stdio.h>
#include "lua.hpp"
int main()
lua_State* L;//lua私有栈
L = lua_open();//打开lua,返回lua虚拟机
luaL_openlibs(L);//加载基础库
luaL_dofile(L,"test.lua");//执行脚本
lua_getglobal(L, "add");//将lua全局表中的add压栈
if (!lua_isfunction(L, -1))//判断是否是函数
printf("function my_pow not found");
return -1;
lua_pushnumber(L, 2);//压入参数
lua_pushnumber(L, 8);
lua_pcall(L, 2, 1, 0);//调用函数,有返回值会压入到栈中
if (!lua_isnumber(L, -1))//判断返回值
perror("return fail!\\n");
return -1;
LUA_NUMBER res = lua_tonumber(L, -1);//获得栈顶元素
printf("res = %f\\n", (float)res);
lua_close(L);//关闭Lua
return 0;
lua脚本
function my_pow(x, y)
return x^y
end
print(my_pow(2, 8))
function add(x, y)
return x+y
end
C/C++调用全局表中的函数
C函数
#include <stdio.h>
#include "lua.hpp"
int main()
lua_State* L;//lua私有栈
L = lua_open();//打开lua,返回lua虚拟机
luaL_openlibs(L);//加载基础库
luaL_dofile(L, "test.lua");//执行脚本
//将_G 中表名为testTable压栈
lua_getglobal(L, "testTable");
if (!lua_istable(L, -1))
printf("table push fail!\\n");
return -1;
//将表中对应函数键值压栈
lua_pushstring(L, "add");
//会将add键值出栈,将testTable["add"]压栈
lua_gettable(L, -2);
if (!lua_isfunction(L, -1))
printf("table function push fail!\\n");
return -1;
//将参数压栈
lua_pushnumber(L, 1);
lua_pushnumber(L, 2);
//调用函数,将参数函数弹出栈,将返回结果压入栈
lua_pcall(L, 2, 1, 0);
LUA_NUMBER res = lua_tonumber(L, -1);
printf("%f", (float)res);
lua_close(L);//关闭Lua
return 0;
lua脚本
testTable =
function testTable.add(x, y)
return x + y
end
function testTable.sub(x, y)
return x -y
end
在lua中调用C函数
C函数
#include <stdio.h>
#include "lua.hpp"
int printHello(lua_State* L)
printf("hello world!\\n");
return 0;
int add(lua_State* L)
int x = luaL_checknumber(L, -1);//取出栈顶两个元素
int y = luaL_checknumber(L, -2);
int res = x + y;
lua_pushnumber(L, res);
//返回值为C函数压栈数据数量
return 1;
void registerFunc(lua_State* L, const char* funcName, lua_CFunction func)
//lua_register(L, funcName, func);//直接将C函数注册进lua
lua_pushstring(L, funcName);//将在lua里的c函数名压栈
lua_pushcclosure(L, func, 0);//将C函数压栈
lua_settable(L, LUA_GLOBALSINDEX);//使得lua中的全局表中_G[funcName]=func,即在lua中增加函数,实现为C函数
int main()
lua_State* L;//lua私有栈
L = lua_open();//打开lua,返回lua虚拟机
luaL_openlibs(L);//加载基础库
registerFunc(L, "c_printhello", printHello);//将C函数注册进lua
registerFunc(L, "c_add", add);
luaL_dofile(L,"test.lua");//执行脚本
lua_close(L);//关闭Lua
return 0;
lua脚本
function test()
c_printhello()
local res = c_add(1, 2)
print(res)
end
--执行函数
test()
将c函数注册进lua
前提
实现的C函数需要是特定的格式,如下:
例子:
int add(lua_State* L)
int x = luaL_checknumber(L, -1);//取出栈顶两个元素
int y = luaL_checknumber(L, -2);
int res = x + y;
lua_pushnumber(L, res);
//返回值为C函数压栈数据数量
return 1;
两种方式
方式一:
lua5.2被移除了
lua_pushstring(L, funcName);//将在lua里的c函数名压栈
lua_pushcclosure(L, func, 0);//将C函数压栈
lua_settable(L, LUA_GLOBALSINDEX);//使得lua中的全局表中_G[funcName]=func,即在lua中增加函数,实现为C函数
方式二:
lua_register(L, funcName, func);//直接将C函数注册进lua
以上是关于Lua与C/C++交互的主要内容,如果未能解决你的问题,请参考以下文章