C++ 调用 Lua 代码
2021-06-05 15:03
标签:接下来 一个 code exec info ace 比较 clu VID 马上要开始实习了,在实习中会用到skynet这个框架,这个框架主要就是由 C 以及 Lua 进行实现的,于是就学习了一下 Lua 的基本语法以及如何使用进行 C++ 和 Lua 的混合编程。 本篇论文主要记录一下如何在C++代码中调用Lua的代码,以及如何让程序跑起来,因为之前看到很多博客虽然都说明了代码怎么写,但始终对于如何让代码跑起来不是很清楚。经过反复折腾总算是能运行起来了,当然作为一个初学者来说,我的方法可能比较麻烦,不应当作为范例,以后也可能会纠正,同时有些地方可能会存在错误,也希望大家能指正我。 主要用到的一些工具: Lua 和 cmake 先学好预备知识,Lua 我是直接看菜鸟的,cmake 是在B站找了个视频看了下,基本看得快各一天就能看完。链接里是我参考的学习资料。 我理解的Lua一方面是一个脚本语言,另一方面也可以当作C/C++的库来使用,有了这个库之后就可以在 C++ 的代码中直接运行 Lua 文件。 首先第一步肯定就是下载 Lua 了,网上有很多教程,然后记住 Lua 的源代码的地址,后面会用到。 然后就可以开始写 Lua 的代码了,首先在项目目录中创建一个 代码中首先进行了 在项目目录中创建一个 这里用 接下来就是如何在 main 函数中调用 Lua 定义的变量及函数。 C++ 和 Lua 的交互主要是靠虚拟栈来实现的。首先 C++ 中会创建出这个虚拟栈L,然后再打开 Lua 的某个代码文件和这个栈进行绑定,虚拟栈是由 C++ 文件创建出来的,又和某个 Lua 代码文件进行了绑定,这就将 C++ 和 Lua 联系起来了。然后只要在 C++ 中将数据入栈,在 Lua 中将数据出栈,或者 Lua 中将数据入栈,在 C++ 中将数据出栈,这样就完成二者的数据交互。 首先是创建这个虚拟栈L( 主要用到 当然绑定和执行一般都是要一块执行的,也有一个将二者合二为一的函数 使用 使用 使用 目前为止已经建立了 cmake 语法这里不再详细说明,首先在项目目录中创建 然后在 在项目文件中创建 然后 cmake 会生成 即可运行,运行结果如下: C++ 调用 Lua 代码 标签:接下来 一个 code exec info ace 比较 clu VID 原文地址:https://www.cnblogs.com/gongqk/p/14626536.htmlC++ 调用 Lua 代码
Lua 代码
lua_code
目录用来存放 Lua 代码,比如写一个 add.lua
文件,代码如下:print("C++ call Lua!!")
str = "I am a student."
tbl = {name="Gong", id=20210405}
function add(x, y)
return x + y
end
print
输出,然后创建了两个全局变量和一个函数,等下会说明如何在 C++ 代码中对这三者进行访问。C++ 代码
src
进行存放 C++ 的源代码,然后在该目录下创建 main.cpp
。首先在头部添加头文件:#include
extern "C"
的原因是 Lua 的库是用 C 实现的,而 C 和 C++ 的编译还是存在着一些细微的差别的,这里主要就是告诉编译器这些文件是用C编译的。1. 创建虚拟栈
luaL_newstate()
),以及打开 Lua 的标准库(luaL_openlibs(L)
),代码如下:lua_State *L = new luaL_newstate();
luaL_openlibs(L);
2. 绑定并执行 Lua 文件
luaL_loadfile(L, lua_path)
进行绑定,以及 luaL_pcall(L, 0, 0, 0)
进行执行(执行之后才能知道这个文件中有哪些变量和函数,这里先不说明后三个参数,只要记住都输入0即可)。二者都是如果失败就返回非0值。int bRet;
if (bRet = luaL_loadfile(L, "../lua_code/add.lua")) {
cout
lua_dofile(L, lua_path)
:if (bRet = luaL_dofile(L, "../lua_code/add.lua")) {
cout
3. 获取 Lua 文件中定义的变量
lua_getglobal(L, name)
函数,获取名为name的变量并置于栈顶,变量名可以是定义的全局变量,也可以是函数名。在用 lua_tostring(L, index)
/ lua_tonumber(L, index)
/ lua_tointeger(L, index)
来获取这个变量。lua_getglobal(L, "str");
string str = lua_tostring(L, -1);
cout
4. 获取 Lua 文件中的 table
lua_getglobal(L, name)
将 table 变量置于栈顶,然后利用 lua_getfield(L, -1, key)
来获取 key 所对应的变量并置于栈顶,然后在获取该变量即可。lua_getglobal(L, "tbl");
lua_getfield(L, -1, "name");
string name = lua_tostring(L, -1);
lua_getfield(L, -2, "id");
int id_ = (int) lua_tointeger(L, -1);
cout
5. 获取 Lua 文件中定义的函数
lua_getglobal(L, name)
将函数置于栈顶,然后再调用 lua_push*
传入参数,并调用 lua_pcall(L, param_num, return_num, 0)
来调用函数,调用完成后返回值会存放在栈顶中。lua_getglobal(L, "add");
lua_pushnumber(L, 123);
lua_pushnumber(L, 145);
lua_pcall(L, 2, 1, 0);
double res = lua_tonumber(L, -1);
cout
6.
main.cpp
完整代码#include
cmake
src/main.cpp
以及 lua_code/add.lua
两个文件,接下来就是如何运行的问题。由于 Lua 已经编译为了库文件,在 Lua 安装目录的 src
子目录中,该目录中也存放了 Lua 库的头文件,所以在 CMakeLists.txt
文件中添加上头文件以及库文件路径,并将 Lua 库文件链接到生成的目标文件中即可。CMakeLists.txt
文件,内容如下:cmake_minimum_required(VERSION 3.10)
project(CppCallLua)
add_subdirectory(./src)
src
子目录中再创建一个 CMakeLists.txt
文件,用于编译源目录下文件:# 添加 lua 头文件以及库文件路径
include_directories(/Users/gongqinkang/apps/lua-5.3.5/src)
link_directories(/Users/gongqinkang/apps/lua-5.3.5/src)
# 设置可执行文件的输出目录为 build/bin/
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
# 添加可执行文件
aux_source_directory(. DIR_SRC)
add_executable(main ${DIR_SRC})
# 链接 lua 库
target_link_libraries(main lua)
编译运行
build
目录,此时整个项目目录结构为:cd
进入 build
目录,在 build
目录下运行:> cmake ..
> make
Makefile
文件,然后用 make
进行编译,最后产生的可执行文件在 build/bin/
目录下,然后在 build
目录下输入:> ./bin/main