luajit开发文档wiki中文版(二) LuaJIT 扩展
2022年6月9日09:39:53
luajit开发文档中文版(一)下载和安装
luajit开发文档中文版(二)LuaJIT扩展
luajit开发文档中文版(三)FAQ 常见问题
luajit开发文档wiki中文版(二) LuaJIT 扩展
luajit开发文档wiki中文版(三)性能调优和测试
luajit开发文档wiki中文版(四) LuaJIT 内部结构
luajit开发文档wiki中文版(五) 系统集成
luajit开发文档wiki中文版(六) LuaJIT 开发
可用 FFI 绑定列表
请注意,大多数开发人员更喜欢只绑定到他们实际需要的少数库调用。例如,rmdir()
绑定只是与 LuaJIT FFI 的一行。与 eg 的简单绑定zlib
只需要两打行,请参阅FFI 教程。你可以在网上找到很多这样的例子。
以下列表仅显示较大或较全面的库绑定:
核心操作系统库
- ljsyscall:Linux 系统调用。
- luapower/winapi:Win32 API
- luapower/objc : Objective-C & Cocoa 桥
- luapower/pthread:POSIX 线程(Linux/OSX/Winpthreads 可移植子集)
- luapower/time : 时间、时钟、睡眠 (Linux/OSX/Windows)
- LJIT2Win32:核心 Windows 库。
- ljf-com:微软 COM。
- LJIT2RPi : Raspberry Pi 的 VideoCore。
- TINN:Windows API 集,包括一个外壳。
- lua-resty-fileinfo:libmagic。
数据库
- luajit-mysql:MySQL。
- luapower/mysql:MySQL。
- LJIT2Sophia:Sophia。
- lsqlite3-ffi:SQLite。
- LJIT2SQLite:SQLite。
- LJSQLite3:SQLite3。
- mongolua:MongoDB 和 BSON 库。
- luajit-unqlite:UnQLite。
图形
- glua :OpenGL/GLUT。
- LuaJIT-GLFW:OpenGL 和 GLFW。
- luajit-glfw:GLFW v3.1.1-v3.2.0。
- LJIT2Khronos:Khronos(OpenGL、EGL、OpenCL、OpenVG)
- luapower/cairo : cairo 图形库。
- luapower/clipper : 剪裁器(多边形剪裁)。
- luapower/giflib:giflib。
- luapower/nanojpeg:nanojpeg。
- luapower/libjpeg:libjpeg。附带 libjpeg-turbo 二进制文件。
- luapower/freetype:自由类型。
- wklua:wkhtmltopdf。
- LuaJIT-SDL2:带有线程和音频的 SDL2。
音频视频
- openal-lua-ffi:OpenAL。
- wavpack-lua-ffi:Wavpack。
- libsndfile-lua-ffi:libsndfile。
- mad-lua-ffi:MAD(MPEG 音频解码器)。
- ffmpeg-lua-ffi:ffmpeg。
- LJIT2X264:X264
消息和事件
- epoll_ffi:epoll。
- ffi_libmosquitto:libmosquitto(MQTT 客户端库)。
联网
- luajit-ffi-enet:Enet。
编码和解码
- luajit-msgpack-pure:消息包。
- iconv-lua-ffi:iconv。
- LJIT2Http_Parser:HTTP 解析器。
- luapower/expat : expat XML 解析器。
- luapower/genx : genx XML 生成器。
- lua-resty-libcjson : (cJSON) JSON 编码器/解码器。
- lua-resty-hoedown : Markdown 和 SmartyPants 解析器。
加密货币
- lua-libssh : libssh (OpenSSH)。
- LJIT2WinCNG:WinCNG。
- luapower/md5:MD5。
- luapower/sha2:SHA-256、SHA-384、SHA-512。
- lua-resty-scrypt:Scrypt(密码)散列。
- lua-bcrypt : OpenBSD bcrypt 的 LuaJIT FFI 绑定(仅在 OpenBSD 上可用)
压缩
- luapower/zlib:zlib。
- luapower/minizip : minizip。
- lua-resty-snappy:snappy。
- ljlz4:lz4。
游戏引擎
- allua: Allegro 5。
跨语言 RPC
- Motan-OpenResty:一个跨语言的 RPC 框架。
跨语言桥梁
- TLC(Tiny Lua Cocoa 桥):Objective-C 桥。
统一码
- luapower/libunibreak : Unicode 换行和分词。
杂项
- ufo:为 OSX/Windows 和其他平台预编译的二进制文件。绑定:Cairo、Pixman、SDL 1.3、zlib、libpng、libbz2、ZeroMQ、Expat、Freetype、GLFW、APR、AntTweakBar、OpenGL、OpenCL。
- luapower/hunspell : hunspell(拼写检查)
- luajit-tcc : 微型 C 编译器。
- luapower/luastate : 绑定到 Lua C API 以创建独立的 Lua 状态
- luapower/dynasm : 使用Lua 的DynASM
- luapower/cbframe:低级 FFI 回调帧(解决 FFI ABI 限制的方法)
- luajit-gmp:GNU 多精度库。
- lua-clang : C 接口到 Clang 的绑定。
可用软件包列表
由于 Lua 是一种非常简洁的语言,具有最少的预安装库,因此 Lua 程序员可用的大部分功能来自对外部库执行互操作调用。特别是 LuaJIT,为调用外部库提供了极好的支持。如果您想要访问目标系统上的预编译库,那么您需要使用FFI 绑定库。
如果您想要的是 100% 用 Lua 编写的代码,没有额外的库依赖项,那么您可能想要获取此处列出的包之一。
标准是:
- 100% LuaJIT 代码
- 不依赖外部库
您的用例是否通过使用本机包而得到极大改进取决于您的标准。一个关键的好处可能只是你不必携带和维护一个单独的库,它是用与 Lua 不同的语言编写的。
编码和解码
- luajit-msgpack-pure:消息包。
- luajit-bson : BSON
加密
- lrc4 : RC4 流密码
标准功能
- LAPHLibs:各种函数,包括utf-8、crc、md5、streams、xml
- LPegLJ:基于 PEG(解析表达式)和简化 RegEx(正则表达式)al la LPeg的字符串模式匹配。
- luapower/utf8 : utf-8 基础
- Lua Fun : 为跟踪 JIT 优化的函数式编程库
系统库
- LJSyscall : Linux 系统接口
- LJLinenoise:使用 LJSyscall 进行行编辑(linenoise 的端口)
- luapower/stdio : 带缓冲区的标准 i/o
数值库
- Rclient:通过 Rserve 将 LuaJIT 与 R 语言接口
日期时间库
- 时间:根据公历的日期和期间
数据结构
- slice : 数组切片
- lds - LuaJIT 数据结构:类似 STL 的容器,例如 Vector 和 Queue(计划中的哈希和树)
- luapower/ringbuffer : 双向环形缓冲区
- luapower/heap:优先级队列
图形
- luapower/affine2d : 2D 仿射变换
- luapower/bitmap : 位图转换
- luapower/bmp : BMP 文件的加载和保存
束包
- UFO - 包括 OpenGL 和 glu、OpenCL、SDL、ZeroMQ、GLFW
FFI参数化类型
参数化类型是 LuaJIT FFI 的一个特性。它使人们能够动态地指定 FFI C 声明。它对泛型编程很有用,类似于使用C++ 模板或Java 泛型的原因。
此功能于 2012 年 6 月推出,在 LuaJIT 2.0.1 及更高版本中可用。
要使用此功能,您可以将字符放在由and$
使用的 C 类型声明中。当你使用这个声明时,你会传递参数。这些参数可以是ctype / cdata、字符串或数字。ffi.cdef
ffi.type
以下是一些示例(单独来看并不是很有趣):
ffi.typeof("$ *", foo_t)
ffi.typeof("struct { $ k; $ v; }[?]", foo_t, bar_t)
ffi.typeof("uint8_t[$][$]", width, height)
邮件列表中的文档
以下内容发布在 LuaJIT 邮件列表中。
该$
字符是在 C 类型声明中被参数替换的标记:
-
ctype或cdata参数被解释为匿名 typedef。您可以使用它来构造派生类型,例如
ffi.typeof("$*", ct)
是指向 的指针ct
,或者"$[10]"
是 10 元素数组。与简单的字符串连接不同,这适用于所有情况(例如指向函数指针的指针)。 -
字符串参数被视为标识符或关键字,除了字符串不会再次解析或拆分为单词(这不是简单的文本替换)。您可以将其用于字段名称、函数名称、参数名称等。
[我正在考虑是否应该删除关键字并在字符串上键入查找。这将允许您对字段使用任意名称,即使它们与关键字或 typedef 冲突。我可能会在编写文档之前更改它。]
-
数字参数被视为整数。您可以使用它来构造固定大小的数组。在某些情况下,您可能更喜欢 VLA。它也适用于多维类型。例如:
local matrix_t = ffi.typeof("uint8_t[$][$]", width, height)
...
local m = matrix_t()
仅解析参数化类型ffi.typeof()
。ffi.cdef()
其他函数,例如ffi.new()
,不这样做,因为它们已经接受了其他参数(例如初始化器)。我想混合两种论点会太混乱。
无论如何,参数化类型是一个很好的工具,但你会想谨慎使用它!
您会想到在 C++ 中使用模板的典型场景:例如,构建任意类型的堆栈或队列。这些都需要创建一个元素类型的数组,现在真的很容易做到。[贾斯汀的用例]
另一个例子是匿名结构的派生类型。这避免了结构命名空间的污染。[亨克的用例]
堆栈示例
Mike在 LuaJIT 邮件列表上发布了这个示例:
local ffi = require("ffi")
local function stack_iter(stack)
local top = stack.top
if top > 0 then
stack.top = top-1
return stack.slot[top-1]
end
end
local stack_mt = {
__new = function(tp, max)
return ffi.new(tp, max, 0, max)
end,
__index = {
push = function(stack, val)
local top = stack.top
if top >= stack.max then error("stack overflow") end
stack.top = top + 1
stack.slot[top] = val
end,
pop = function(stack)
local top = stack.top
if top <= 0 then error("stack underflow") end
stack.top = top-1
return stack.slot[top-1]
end,
iter = function(stack)
return stack_iter, stack
end,
}
}
local function makestack(ct)
local tp = ffi.typeof("struct { int top, max; $ slot[?]; }", ct)
return ffi.metatype(tp, stack_mt)
end
local stack_t = makestack(ffi.typeof("double"))
local stack = stack_t(100)
for i=1,100 do stack:push(i) end
for x in stack:iter() do io.write(x, " ") end
io.write("