luajit ffi 小结
Lua 是一种语法简单,上手快的语言,虽然原生库比较少,但是可以方便的和 C 语言互相调用,常被用于脚本嵌入到 C 程序中。如 Redis 中可以加载 Lua 脚本,作用类似于存储过程,Nginx 中 lua-nginx-module 模块更是将 Lua 的这种特性发挥到极致。
使用 Lua 如何调用 C 的函数,个人认为是每一个 Lua 开发者必学的内容。Lua 调用 C 程序有两种方法,一种是使用 lua C API,另一种方法就是使用 luajit 提供的 ffi 库来调用 C 程序。本文主要是对 luajit ffi 的研究总结。
luajit ffi
luajit 和 lua 一样,是可以直接安装在操作系统中的,相关介绍直接参考官网 luajit。个人测试效果来看,luajit 的执行效率远高于 lua,大概是 8 倍左右。openresty 的 lua-nginx-module 模块就是将 luajit 集成到了 Nginx 中,实现在 Nginx 中执行 Lua 脚本
luajit ffi 是 luajit 提供给 Luaer 使用 Lua 调用 C 函数的 Lua 库,使用该库,Luaer 不用再去操作复杂的 Lua 栈来粘合两种程序代码,luajit ffi 官方资料。
引入 luajit ffi 库
local ffi = require("ffi")
在 Lua 中调用 C 函数
和 lua 的 C API 一样,Lua 调用 C 函数,需要将 C 函数编译成链接库。区别在于 C API 查找 C 的 Lua 库是在 package.cpath 路径下进行查找,而这些库函数使用 Lua 栈接口进行编写。而 luajit 对于 C 链接库的引用遵从于普通 C 库的引用方式,先在 /usr/lib(/usr/lib64),/lib(/lib64) 目录下查找,再到用户自定义的 LD_LIBRARY_PATH 下查找。
本节涉及接口:
- ffi.cdef[[c_function define]]
- ffi.C
- ffi.load(name [,global])
调用 C 标准库函数
对于 C 标准库函数引用,需要引入函数,函数声明
ffi.cdef[[c_function define]]
调用 C 函数
ffi.C.c_function
如:
local ffi = require("ffi") ffi.cdef[[ int printf(const char *fmt, ...); int strcasecmp(const char *s1, const char *s2); ]] ffi.C.printf("Hello %s!\n", "world") ret = ffi.C.strcasecmp("Hello", "hello") print(ret) ret = ffi.C.strcasecmp("Hello", "hello1") print(ret)
输出结果
[root@AlexWoo-CentOS lua]# luajit ffic.lua Hello world! 0 -49
调用自定义的 C 函数
调用自定义的 C 函数,首先要将自定义的 C 函数编译成链接库
[root@AlexWoo-CentOS lua]# cat ffimyc.c int add(int x, int y) { return x + y; } [root@AlexWoo-CentOS lua]# gcc -g -o libffimyc.so -fpic -shared ffimyc.c
比调用 C 标准库函数,需要在 Lua 中引入相应的库
ffi.load(name [,global])
这里第二个参数如果为 true,则该库被引入全局命名空间,这里使用 ffi.load 需要注意两点:
链接库文件必须在 C 的动态链接库查找路径中,否则会报类似错误: