Lua与C++如何相互交互
通过lua虚拟栈隔离Lua和C/C++类型和彼此内存的差异来实现数据及函数互相调拥。
1.相互通信:
C++与Lua基于lua虚拟栈进行数据交换
2.通信流程如下:
1).C++与lua通信流程:
C++、Lua示例代码:
test.cpp 文件
lua_State* L = luaL_newstate();
luaL_openlibs(lstate);
1.lua_getglobal("mTable");
2.lua_pushstring(L, "name");
int ret = lua_pcall(L, 1, 0, 0);
3.lua_gettable(L, -2);
4.lua_tostring(L, -1);
test.lua 文件
1.a = 1
2.mTable = {name = "zw", num = 123}
3.function f()
print(a)
end
stack_zw.png
**2).Lua与C通信流程:
Lua、C源码示例:
lua_CFunction:
static int str_find (lua_State *L) {
return str_find_aux(L, 1);
}
luaL_Reg数组:
static const luaL_Reg strlib[] = {
{"find", str_find},
{NULL, NULL}
};
入栈相关:
LUAMOD_API int luaopen_string (lua_State *L) {
luaL_newlib(L, strlib);
createmetatable(L);
return 1;
}
添加到lua全局table中:
LUALIB_API void luaL_openlibs (lua_State *L) {
const luaL_Reg *lib;
/* "require" functions from 'loadedlibs' and set results to global table */
for (lib = loadedlibs; lib->func; lib++) {
luaL_requiref(L, lib->name, lib->func, 1);
lua_pop(L, 1); /* remove lib */
}}
栈上弹出一个值,并将其设为全局table变量 modname 的值。
LUALIB_API void luaL_requiref (lua_State *L, const char *modname,
lua_CFunction openf, int glb) {
...
if (glb) {
lua_pushvalue(L, -1); /* copy of module */
lua_setglobal(L, modname); /* _G[modname] = module */
}
}
local str = "zwenzhou"
function func()
print(string.find(str, "z")) -- find方法就是luaL_Reg结构体数组“find”对应的str_find C函数的具体实现。
end
stack2_zw.png
业务实现具体可参照lua源码init.c 库初始化方式,首先创建C闭包(Lua需要调用的宿主函数)并把这个 C (cfunction)闭包压到栈上同时设置到Lua全局table中,Lua通过创建对应的luaL_Reg结构体name(理解为闭包key)对应的lua_CFunction(函数指针),即可访问栈中的lua_CFunction,最终达到Lua访问C++的目的。Lua不能随意访问宿主(C/C++)函数,前提必须有“注册”(个人理解是出于安全考虑)。
3.综述:
通过这个lua虚拟栈作桥梁,当C/C++想调用lua中一个值时,Lua将数值压入lua虚拟栈中,然后通过lua提供api操作栈来读取栈顶的值。
网友评论