JAVA全系列 教程
3762个小节阅读:7092k
目录
C语言快速入门
JAVA全系列 教程
面向对象的程序设计语言
Python全系列 教程
Python3.x版本,未来主流的版本
人工智能 教程
顺势而为,AI创新未来
大厂算法 教程
算法,程序员自我提升必经之路
C++ 教程
一门通用计算机编程语言
微服务 教程
目前业界流行的框架组合
web前端全系列 教程
通向WEB技术世界的钥匙
大数据全系列 教程
站在云端操控万千数据
AIGC全能工具班
A A
White Night
ffi是LuaJIT 里最有价值的一个库,它极大地简化了在 Lua 代码里调用C接口的工作,不需要编写烦琐的 Lua/C 绑定函数,只要在 Lua 代码里嵌入 函数或数据结构的声明,无须额外的代码即可直接访问,非常方便,而且执行效率比传统的战方式更高。
ffi 库不仅可以调用系统函数和 OpenResty 内部的 函数,还可以加载 so 形式的动态库,调用动态库里的函数,从而轻松灵活地扩展 Lua 的功能。
ffi 库 词汇
noun | Explanation |
---|---|
cdecl | A definition of an abstract C type(actually, is a lua string) |
ctype | C type object |
cdata | C data object |
ct | C type format, is a template object, may be cdecl, cdata, ctype |
cb | callback object |
VLA | An array of variable length |
VLS | A structure of variable length |
FFI.API
xxxxxxxxxx
local ffi = require "ffi"
ffi.cdef
语法: ffi.cdef(def)
功能: 声明 C 函数或者 C 的数据结构,数据结构可以是结构体、枚举或者是联合体,函数可以是 C 标准函数,或者第三方库函数,也可以是自定义的函数,注意这里只是函数的声明,并不是函数的定义。声明的函数应该要和原来的函数保持一致。
xxxxxxxxxx
ffi.cdef[[
typedef struct foo { int a, b; } foo_t; /* Declare a struct and typedef. */
int printf(const char *fmt, ...); /* Declare a typical printf function. */
]]
注意: 所有使用的库函数都要对其进行声明,这和我们写 C 语言时候引入 .h 头文件是一样的。
顺带一提的是,并不是所有的 C 标准函数都能满足我们的需求,那么如何使用 第三方库函数 或 自定义的函数 呢,这会稍微麻烦一点,不用担心,你可以很快学会。: ) 首先创建一个 myffi.c
,其内容是:
xxxxxxxxxx
int add(int x, int y)
{
return x + y;
}
接下来在 Linux 下生成动态链接库:
xxxxxxxxxx
gcc -g -o libmyffi.so -fpic -shared myffi.c
为了方便我们测试,我们在 LD_LIBRARY_PATH
这个环境变量中加入了刚刚库所在的路径,因为编译器在查找动态库所在的路径的时候其中一个环节就是在 LD_LIBRARY_PATH
这个环境变量中的所有路径进行查找。命令如下所示。
xxxxxxxxxx
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:your_lib_path
在 Lua 代码中要增加如下的行:
xxxxxxxxxx
ffi.load(name [,global])
ffi.load
会通过给定的 name
加载动态库,返回一个绑定到这个库符号的新的 C 库命名空间,在 POSIX
系统中,如果 global
被设置为 ture
,这个库符号被加载到一个全局命名空间。另外这个 name
可以是一个动态库的路径,那么会根据路径来查找,否则的话会在默认的搜索路径中去找动态库。在 POSIX
系统中,如果在 name
这个字段中没有写上点符号 .
,那么 .so
将会被自动添加进去,例如 ffi.load("z")
会在默认的共享库搜寻路径中去查找 libz.so
,在 windows
系统,如果没有包含点号,那么 .dll
会被自动加上。
下面看一个完整例子:
xxxxxxxxxx
local ffi = require "ffi"
local myffi = ffi.load('myffi')
ffi.cdef[[
int add(int x, int y); /* don't forget to declare */
]]
local res = myffi.add(1, 2)
print(res) -- output: 3 Note: please use luajit to run this script.
除此之外,还能使用 ffi.C
(调用 ffi.cdef
中声明的系统函数) 来直接调用 add
函数,记得要在 ffi.load
的时候加上参数 true
,例如 ffi.load('myffi', true)
。
完整的代码如下所示:
xxxxxxxxxx
local ffi = require "ffi"
ffi.load('myffi',true)
ffi.cdef[[
int add(int x, int y); /* don't forget to declare */
]]
local res = ffi.C.add(1, 2)
print(res) -- output: 3 Note: please use luajit to run this script.