一、Lua 定位
嵌入式言语:C 言语具有控制权, Lua 言语被用作库
可扩展言语:Lua 言语具有控制权,C 言语被用作库
不管哪一种,都需求用到 C API 进行交互。
C API 中大大都函数不会检查参数的正确性,所以有必要确保在调用前确保参数的合法性,一旦犯错,程序会崩溃而不会收到标准的错误信息。
可以经过运用宏界说 LUA_USE_APICHECK 来启用一些一致性检查
二、什么是 C API
C API 包括读写 Lua 全局变量的函数、调用 Lua 函数的函数、运行 Lua 代码段的函数、以及注册 C 函数(用于后面可以被 Lua 代码调用)的函数等。
经过 C API 就可以打通了 C 调用 Lua 以及 Lua 调用 C 的途径。
三、将 Lua 集成到 C++ 项目中
第一步,下载需求的 Lua 版别源码
进入官网 www.lua.org/ftp/ 进行下载,我运用的是 5.4.4
下载后解压,进入到 src 目录,将目录下的文件复制到项目中的一个文件夹下。
以 Lua_CPP_2022
项目为例,放置在项目下的 lua_lib/lua-5.4.4
目录中。
第二步,编写 cmake 将源文件链接
# 设置 LUA_DIR 指向 lua-5.4.4 目录
set(LUA_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lua-5.4.4)
# 设置 Lua 源码
set(LUA_RUNTIME_SOURCES
"${LUA_DIR}/lapi.c"
"${LUA_DIR}/lauxlib.c"
"${LUA_DIR}/lbaselib.c"
"${LUA_DIR}/lcode.c"
"${LUA_DIR}/lcorolib.c"
"${LUA_DIR}/lctype.c"
"${LUA_DIR}/ldblib.c"
"${LUA_DIR}/ldebug.c"
"${LUA_DIR}/ldo.c"
"${LUA_DIR}/ldump.c"
"${LUA_DIR}/lfunc.c"
"${LUA_DIR}/lgc.c"
"${LUA_DIR}/linit.c"
"${LUA_DIR}/liolib.c"
"${LUA_DIR}/llex.c"
"${LUA_DIR}/lmathlib.c"
"${LUA_DIR}/lmem.c"
"${LUA_DIR}/loadlib.c"
"${LUA_DIR}/lobject.c"
"${LUA_DIR}/lopcodes.c"
"${LUA_DIR}/loslib.c"
"${LUA_DIR}/lparser.c"
"${LUA_DIR}/lstate.c"
"${LUA_DIR}/lstring.c"
"${LUA_DIR}/lstrlib.c"
"${LUA_DIR}/ltable.c"
"${LUA_DIR}/ltablib.c"
"${LUA_DIR}/ltm.c"
"${LUA_DIR}/lua.c"
"${LUA_DIR}/lundump.c"
"${LUA_DIR}/lutf8lib.c"
"${LUA_DIR}/lvm.c"
"${LUA_DIR}/lzio.c"
)
add_library(
LuaLib
SHARED
${LUA_RUNTIME_SOURCES}
)
第三步,将 cmake 文件链接到主项目
# 将 lua_lib/lua-5.4.4 目录添加至编译器的查找目录中
# 这样运用 Lua 的源文件时,#include 的文件路径就不需求运用 "lua_lib/lua-5.4.4" 了
# 假设没有这一句,运用 "lua.hpp" ,就需求 #include "lua_lib/lua-5.4.4/lua.hpp"
# 有了这一句,就只需求 #include "lua.hpp"
include_directories(lua_lib/lua-5.4.4)
# 将子目录添加到构建中
# 参数 source_dir( 即这儿的 lua_lib )指定源 CMakeLists.txt 和代码文件地点的目录
# 这样就会把 lua_lib/CMakeLists.txt 加入到构建中
add_subdirectory(lua_lib)
# 添加链接库
target_link_libraries(Lua_CPP_2022 LuaLib)
这样就将 Lua 源代码链接进我们的项目了
第四步,运用以下代码进行验证是否集成成功
#import "lua.hpp"
/**
* 验证 Lua 集成是否成功
*/
void verification() {
int error;
lua_State *L = luaL_newstate();
luaL_openlibs(L);
error = luaL_loadstring(L, "print(\"jiang\")") || lua_pcall(L, 0, 0, 0);
if (error) {
fprintf(stderr, "%s\n", lua_tostring(L, -1));
lua_pop(L, 1);
}
lua_close(L);
}
int main() {
verification();
return 0;
}
// --> jiang
四、引进的头文件简介
假设是运用 C 言语的话,则直接运用以下进行引证 Lua 头文件
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
假设运用 C++ 则需求嵌套 extern ,或是直接引证 lua.hpp
extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
// 或是运用 lua.hpp
#import "lua.hpp"
其实 lua.hpp 内部也便是用 extern 进行嵌套这些头文件。
1、lua.h
lua.h
中为 Lua 供应的基础函数,全部的函数都以 lua_
最初。
其中包括了 “创立新 Lua 环境的函数”、“调用 Lua 函数的函数”、“读写环境中的全局变量的函数”,以及 “注册供 Lua 言语调用的新函数的函数” 等等。
2、luaxlib.h
是一个辅佐库,是根据 lua.h 供应的基础 API 供应更高层次的笼统,函数都以 luaL_
最初。
luaxlib.h 供应的是对常见使命的实用性,lua.h 供应的是经济性和正交性。
3、lualib.h
Lua 中默许不带有任何的标准库,而全部的标准库都被打包成不同的包。lualib.h 中包括了翻开这些库的函数
运用 luaL_openlibs
则翻开了全部的标准库。
五、 lua_State
Lua 标准库中没有界说任何 c 言语全局变量,全部状态都保存在动态结构体 lua_Stata 中,而 Lua 中的全部函数都有接收 lua_State 类型的参数,从而可以完成多线程。
宿主程序 C/C++ 会经过 lua_State 跟 Lua 进行交互,一般的操作过程为如下所示:
// 第一步:创立 lua_State
lua_State *L = luaL_newstate();
// 第二步:翻开全部标准库
luaL_openlibs(L);
// 第三步:经过 lua_State 进行 Lua 的交互
// 第四步:关闭 lua_State
lua_close(L);
当然第三步的逻辑会许多,lua_State
可以被一直持有,一直到不需求的时分再履行第四步进行关闭开释内存。
第三步的 C/C++ 与 Lua 交互细节后续会有文章具体同享。
1、标准库
上面所述的标准库是指 Lua 中的 string
、math
等标准库,Lua 为了让言语最为精炼,所以初始化的时分是不默许加载的。
lua_openlibs
会加载全部的标准库,假设不需求加载全部,可以运用以下的函数进行加载需求的标准库:
函数 | 描述 |
---|---|
luaopen_base | 基础模块,包括: – 全局函数(例如 print 等) – 全局常量(nil 等) – 中心库函数(load 等) – 字符串操作函数 – 数学函数 – 表操作函数 – 迭代器函数(ipairs 等) – 错误处理函数(error 等) |
luaopen_package | 包管理模块 |
luaopen_coroutine | 协程模块 |
luaopen_table | 表操作模块 |
luaopen_io | 输入输出模块 |
luaopen_os | 操作系统模块 |
luaopen_string | 字符串处理模块 |
luaopen_math | 数学库模块 |
luaopen_utf8 | utf8 编码处理模块 |
luaopen_debug | 调试模块 |
六、写在最后
Lua 项目地址:Github传送门 (假设对你有所协助或喜欢的话,赏个star吧,码字不易,请多多支撑)
假设觉得本篇博文对你有所启示或是解决了困惑,点个赞或关注我呀。
公众号查找 “江澎涌”,更多优质文章会第一时间同享与你。