基于linux 平台的测试
1. 获得源码
关于lua的介绍以及如何获取源码建议读者去这个网址获取
http://www.lua.org/
1.1 linux 下的安装编译
http://www.lua.org/download.html
安装和编译的方法这里提供了,建议使用这种方法进行下载和安装。
curl -R -O http://www.lua.org/ftp/lua-5.4.3.tar.gz
tar zxf lua-5.4.3.tar.gz
cd lua-5.4.3
make all test
安装使用的是 install方法,会自动将生成的 动态库 以及lua等文件拷贝到系统的默认路径下
make install
笔者再实际的使用中遇到了链接上的问题(自己写的代码链接 lua静态库的时候提示错误),make 的参数需要加上 -fPIC 需要修改一下 lua的makefile 文件 。读者如果遇到了在改!
1.2 windows 下的下载和编译
如果是windws 平台下的话可以直接把地址赋值到浏览器 会弹出下载框
注意 编写时间 2021-06 未来会有更新的版本!!!!
http://www.lua.org/ftp/lua-5.4.3.tar.gz
接下来就是解压,这里就随便找一个解压软件就可以了,一般的软件虽然没法压缩生成 tar.gz 的压缩包 但是解压应该还是不成问题的。
解压完之后大约有这些文件
C:\Users\xxxxxxxxxxx\Desktop\lua\lua-5.4.3>tree /F
卷 Windows-SSD 的文件夹 PATH 列表
卷序列号为 B4D2-5835
C:.
│ Makefile # 顶层的makefile文件,
│ README # 简介,基本没用
│
├─doc
│ contents.html
│ index.css
│ logo.gif
│ lua.1
│ lua.css
│ luac.1
│ manual.css
│ manual.html # 编程手册
│ osi-certified-72x60.png
│ readme.html # 真正的readme!!!
│
└─src
lapi.c
lapi.h
lauxlib.c
lauxlib.h
lbaselib.c
lcode.c
lcode.h
lcorolib.c
lctype.c
lctype.h
ldblib.c
ldebug.c
ldebug.h
ldo.c
ldo.h
ldump.c
lfunc.c
lfunc.h
lgc.c
lgc.h
linit.c
liolib.c
ljumptab.h
llex.c
llex.h
llimits.h
lmathlib.c
lmem.c
lmem.h
loadlib.c
lobject.c
lobject.h
lopcodes.c
lopcodes.h
lopnames.h
loslib.c
lparser.c
lparser.h
lprefix.h
lstate.c
lstate.h
lstring.c
lstring.h
lstrlib.c
ltable.c
ltable.h
ltablib.c
ltm.c
ltm.h
lua.c
lua.h
lua.hpp
luac.c
luaconf.h
lualib.h
lundump.c
lundump.h
lutf8lib.c
lvm.c
lvm.h
lzio.c
lzio.h
Makefile
编译方面 我选择的是 mingw
使用的方法就是 mingw32-make
编译之前需要指定平台,虽然lua 的Makefile 里面貌似是能猜 平台,但是 我的是没猜到的,,,,,
打开顶层的Makefile 文件,把 平台从 guess改成 mingw
2. 编译安装源码
接下来进行编译 -j 选项 可以指定进行多核编译,一般是CPU数量的2倍 笔者 6核的处理器.。。。。
当然 lua 本身其实是很小的,即使不加-j 编译起来也是很快的,一般不到一分钟。
C:\Users\xxx\Desktop\lua\lua-5.4.3>mingw32-make -j12
mingw32-make[1]: Entering directory 'C:/Users/xxx/Desktop/lua/lua-5.4.3/src'
mingw32-make "LUA_A=lua54.dll" "LUA_T=lua.exe" \
"AR=gcc -std=gnu99 -shared -o" "RANLIB=strip --strip-unneeded" \
"SYSCFLAGS=-DLUA_BUILD_AS_DLL" "SYSLIBS=" "SYSLDFLAGS=-s" lua.exe
mingw32-make[2]: Entering directory 'C:/Users/xxx/Desktop/lua/lua-5.4.3/src'
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c -o lua.o lua.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c -o lapi.o lapi.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c lcode.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c -o lctype.o lctype.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c -o ldebug.o ldebug.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c -o ldo.o ldo.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c -o ldump.o ldump.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c -o lfunc.o lfunc.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c -o lgc.o lgc.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c llex.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c -o lmem.o lmem.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c -o lobject.o lobject.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c -o lopcodes.o lopcodes.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c lparser.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c -o lstate.o lstate.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c -o lstring.o lstring.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c -o ltable.o ltable.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c -o ltm.o ltm.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c -o lundump.o lundump.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c -o lvm.o lvm.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c -o lzio.o lzio.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c -o lauxlib.o lauxlib.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c -o lbaselib.o lbaselib.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c -o lcorolib.o lcorolib.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c -o ldblib.o ldblib.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c -o liolib.o liolib.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c -o lmathlib.o lmathlib.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c -o loadlib.o loadlib.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c -o loslib.o loslib.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c -o lstrlib.o lstrlib.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c -o ltablib.o ltablib.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c -o lutf8lib.o lutf8lib.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -DLUA_BUILD_AS_DLL -c -o linit.o linit.c
gcc -std=gnu99 -shared -o lua54.dll lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o lundump.o lvm.o lzio.o lauxlib.o lbaselib.o lcorolib.o ldblib.o liolib.o lmathlib.o loadlib.o loslib.o lstrlib.o ltablib.o lutf8lib.o linit.o
strip --strip-unneeded lua54.dll
gcc -std=gnu99 -o lua.exe -s lua.o lua54.dll -lm
mingw32-make[2]: Leaving directory 'C:/Users/xxx/Desktop/lua/lua-5.4.3/src'
mingw32-make "LUAC_T=luac.exe" luac.exe
mingw32-make[2]: Entering directory 'C:/Users/xxx/Desktop/lua/lua-5.4.3/src'
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_3 -c -o luac.o luac.c
ar rcu liblua.a lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o lundump.o lvm.o lzio.o lauxlib.o lbaselib.o lcorolib.o ldblib.o liolib.o lmathlib.o loadlib.o loslib.o lstrlib.o ltablib.o lutf8lib.o linit.o
ranlib liblua.a
gcc -std=gnu99 -o luac.exe luac.o liblua.a -lm
mingw32-make[2]: Leaving directory 'C:/Users/xxx/Desktop/lua/lua-5.4.3/src'
mingw32-make[1]: Leaving directory 'C:/Users/xxx/Desktop/lua/lua-5.4.3/src'
windows 下的安装可能没那么的方便, 读者需要自己去拷贝文件了,我的mingw 是没有正确的找到安装路径的,
需要把执行lua 的可以把lua.exe 放到环境变量中,也可以直接把生成的exe 文件放到windos环境变量下,至于库文件放在哪里 我也不知道 ,我是直接放到build下 然后直接链接就可以找到。。。。。。。(实际大项目肯定要指定链接路径,读者也不必太担心,这些一般是大佬去完成)
至此 我们就可以愉快的玩 lua 了。接下来分享如何使用c/c++ 生成一个lua 的库文件。以及如何在c/c++ 的函数中拿到lua 传递进来的参数。
2.C/C++ 如何产生一个可以被lua 识别的库文件(linux)
在我的实际产品开发中一般是使用lua 调用c的动态库,也就是 我们给客户提*品的api ,然后我们使用C++ 实现这些产品所特有的api. 然后给用户提供一个编程的界面,用户点击运行程序,我们就先执行我们的初始化脚本 接着将我们提供的产品api 注册到全局,再调起用户的程序。
所以我们的api 一般是 库文件的形式存在的,动态库! 然后库文件中实现了进程之间的通讯(共享内存) 进而实现lua脚本代码对产品的控制!
直接上一份简单的代码
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include <unistd.h>
#include <stdio.h>
#define line() {printf("line:%d\n",__LINE__);} // 调试C++ 代码用的
int testFunc(lua_State *L) // 一个简单的可被lua 调用的函数
{
int it = lua_gettop(L);
printf("it = %d\n",it);
return 0;
}
void hook(lua_State* L, lua_Debug* ar) // 钩子函数,可以用于调试,产品中靠这个实现了代码的运行光标功能
{
lua_getinfo(L, "Sl", ar);
// printf("line:%d\n",ar->currentline);
}
static luaL_Reg lua_apis[] =
{ // 函数的对外名称和内部的函数指针
{"testFunc" ,&testFunc}, // 即将注册出去的函数
{ NULL , NULL}// 这是结尾! 必须加上去
};
// 至关重要的一个函数!!!!!
// 函数的名称要符合 luaopen_libxxxx 其中的xxxx 代表你的库文件
// 例如本例子的最终产物就是 : libtest.so 对应的打开函数就是 如下的函数
int luaopen_libtest(lua_State *L)
{
luaL_newlib(L, lua_apis);// 注册api
lua_sethook(L, hook, LUA_MASKLINE, 0); // 设置钩子函数
return 1;
}
对于这样简单的工程 直接一份超级简单的cmake 就可以搞定
project(luatestlib C CXX )
add_library(test SHARED 1.c )
target_link_libraries(test
liblua.a
)
root@jeason:~/lua-5.4.3# tree
.
├── doc
│ ├── contents.html
│ ├── index.css
│ ├── logo.gif
│ ├── lua.1
│ ├── luac.1
│ ├── lua.css
│ ├── manual.css
│ ├── manual.html
│ ├── osi-certified-72x60.png
│ └── readme.html
├── Makefile
├── README
├── src
│ ├── lapi.c
│ ├── lapi.h
......
│ ├── lzio.o
│ └── Makefile
└── test
├── 1.c # 测试 库文件代码
├── 1.lua # 测试脚本
├── build # 编译路径
└── CMakeLists.txt # cmake 文件
4 directories, 116 files
############################ 编译
root@jeason:~/lua-5.4.3# cd test/build/
root@jeason:~/lua-5.4.3/test/build# cmake ..
-- The C compiler identification is GNU 7.5.0
-- The CXX compiler identification is GNU 7.5.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
CMake Warning (dev) at CMakeLists.txt:3 (add_library):
Policy CMP0037 is not set: Target names should not be reserved and should
match a validity pattern. Run "cmake --help-policy CMP0037" for policy
details. Use the cmake_policy command to set the policy and suppress this
warning.
The target name "test" is reserved or not valid for certain CMake features,
such as generator expressions, and may result in undefined behavior.
This warning is for project developers. Use -Wno-dev to suppress it.
-- Configuring done
-- Generating done
-- Build files have been written to: /root/lua-5.4.3/test/build
root@jeason:~/lua-5.4.3/test/build# make
Scanning dependencies of target test
[ 50%] Building C object CMakeFiles/test.dir/1.c.o
[100%] Linking C shared library libtest.so
[100%] Built target test
root@jeason:~/lua-5.4.3/test/build#
test = require("libtest")
test.testFunc()
# 输出 it = 0
test = require("libtest")
test.testFunc(1,2,3,4)
# 输出 it = 4
test = require("libtest")
test.testFunc(1,2,3,4)
testFunc = test.testFunc
testFunc(1,"23")
# it = 4
# it = 2
it 其实就是获得了 lua传入参数的个数!