Lua与C++如何相互交互?

2022-03-03  本文已影响0人  码上述Andy

Lua与C++如何相互交互

通过lua虚拟栈隔离Lua和C/C++类型和彼此内存的差异来实现数据及函数互相调拥。
1.相互通信:
C++与Lua基于lua虚拟栈进行数据交换

lua stack_zw.png

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操作栈来读取栈顶的值。

上一篇下一篇

猜你喜欢

热点阅读