Lua 作为一个运行效率非常高的脚本语言,简单方便,如今很多游戏开发都会用到。今天研究下 c++ 和 lua 是如何交互的~
# 1.c++ 调用 lua
我是在 macos 上实验的,过程应该和 linux 上类似。使用的 lua 版本是 5.3.0.
c++ 调用 lua 原理主要是通过 Lua 的堆栈,一方将传递的参数以及参数个数压入栈中,另一方则在栈中取出参数,并将返回值压入栈中,由另一方取出,实现交互。这个过程和 c++ 和汇编 (如 nasm) 的交互过程很像.
# (i). 添加依赖
将 liblua.a 添加到项目中:
设置 search paths:
Header Search Paths 设置为 lua 安装位置,用来搜索头文件.
Library Search Paths 设置为项目存放.a 库的目录.
# (ii). 代码测试
#include <iostream> | |
extern "C" { | |
#include "lua.h" | |
#include "lualib.h" | |
#include "lauxlib.h" | |
} | |
using namespace std; | |
int main() | |
{ | |
//1. 创建一个 state | |
lua_State *L = luaL_newstate(); | |
//2. 入栈操作 | |
lua_pushstring(L, "Hello World~"); | |
//3. 取值操作 | |
if (lua_isstring(L, 1)) { // 判断是否可以转为 string | |
cout << lua_tostring(L, 1) << endl; // 转为 string 并返回 | |
} | |
//4. 关闭 state | |
lua_close(L); | |
} |
# (iii). 运行代码
运行结果:
# (iv). 求和代码:
lua 代码:
function Sum(a, b) | |
return (a+b); | |
end |
c++ 代码:
#include <iostream> | |
extern "C" { | |
#include "lua.h" | |
#include "lualib.h" | |
#include "lauxlib.h" | |
} | |
using namespace std; | |
int main() | |
{ | |
// 创建 Lua 状态 | |
lua_State *L = luaL_newstate(); | |
if (L == NULL) | |
{ | |
return 0; | |
} | |
// 加载 Lua 文件 | |
int bRet = luaL_loadfile(L, "sum.lua"); | |
if (bRet) | |
{ | |
cout << "load file error" << endl; | |
return 0; | |
} | |
// 运行 Lua 文件 | |
bRet = lua_pcall(L, 0, 0, 0); | |
if (bRet) | |
{ | |
cout << "pcall error" << endl; | |
return 0; | |
} | |
// 读取函数 | |
lua_getglobal(L, "Sum"); // 获取函数,压入栈中 | |
lua_pushinteger(L, 10); // 压入参数 | |
lua_pushinteger(L, 8); // 压入参数 | |
int iRet = lua_pcall(L, 2, 1, 0);// 调用函数,调用完成以后,会将返回值压入栈中,第一个 2 表示参数个数,第二个 1 表示返回结果个数。 | |
if (iRet) // 调用出错 | |
{ | |
const char *pErrorMsg = lua_tostring(L, -1); | |
cout << pErrorMsg << endl; | |
lua_close(L); | |
return 0; | |
} | |
if (lua_isinteger(L, -1)) // 取值输出 | |
{ | |
int sum = lua_tointeger(L, -1); | |
cout << sum << endl; | |
} | |
// 关闭 state | |
lua_close(L); | |
return 0; | |
} |
结果:
# 2.lua 调用 c++
lua 调用 c++ 原理主要是将 c++ 代码编译成.so 动态库,然后在 lua 中用 require 引入,从而调用。通信还是通过 lua 栈来实现的。这里就不展开了。具体可以参考 lua 官方文档,还有 lua5.3 中文文档
# 3.LuaTinker
以上介绍的都是 lua 官方的提供给 c 的一些 api, 较为底层,其实有很多 c++ 和 lua 代码的绑定库,将以上的栈操作以及函数注册等封装了起来,如 LuaBind,LuaTinker 等,我们的项目中使用的就是 LuaTinker.LuaTinker 使用方法可以在 git 仓库中查看.