回调:将 Lua 函数传递给 C
使用 ffi.cast 创建可回调 Lua 代码的 C 回调函数。
回调:将 Lua 函数传递给 C 是 CoddyKit 上的免费 Lua Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Lua Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Lua Academy 课程共包含 4 节课。
什么是 C 回调?
某些 C API 要求您传入一个函数指针,由 C 代码进行回调。FFI 的 ffi.cast 可以从 Lua 函数创建兼容 C 的函数指针。
声明回调类型
首先在 cdef 中声明函数指针类型。
local ffi = require("ffi")
ffi.cdef[[
typedef void (*callback_t)(int event, void *data);
void register_handler(callback_t cb);
]]创建回调
使用 ffi.cast("callback_t", luaFunc) 将 Lua 函数包装为 C 回调。结果是一个 C 函数指针,可以传递给 C 代码。
local function myHandler(event, data)
print("Event:", event)
end
local cb = ffi.cast("callback_t", myHandler)
lib.register_handler(cb)回调生命周期
请保留对回调对象(cb)的 Lua 引用。如果它被 GC 回收,调用该 C 函数指针就会崩溃。请将它存储在生命周期较长的变量或表中。
local callbacks = {} -- prevent GC
callbacks[#callbacks+1] = ffi.cast("callback_t", myHandler)
lib.register_handler(callbacks[#callbacks])使用 C 比较器排序
通过 FFI 回调将 Lua 比较器传递给 C 的 qsort。
ffi.cdef[[
typedef int (*cmp_t)(const void *a, const void *b);
void qsort(void *base, size_t nmemb, size_t size, cmp_t cmp);
]]
local arr = ffi.new("int[5]", {3,1,4,1,5})
local cmp = ffi.cast("cmp_t", function(a, b)
return ffi.cast("int*", a)[0] - ffi.cast("int*", b)[0]
end)
ffi.C.qsort(arr, 5, ffi.sizeof("int"), cmp)
for i = 0, 4 do io.write(arr[i] .. " ") end回调与协程
从 C 调用的 Lua 回调不能让出(调用 coroutine.yield)。C 端不支持 Lua 的协程切换。请将回调设计为不可让出的函数。
回调中的上值
Lua 回调可以正常捕获上值。这样,回调无需使用全局变量即可访问上下文(例如对象或状态表)。
local function makeHandler(ctx)
return ffi.cast("callback_t", function(event, _)
ctx.lastEvent = event -- upvalue access
end)
end信号处理器
通过 FFI 将 Lua 函数注册为 Unix 信号处理器。请注意:信号处理器能够调用哪些 C 函数受到严格限制。
回调内存管理
从 C 端注销回调后,使用 cb:free() 释放回调。泄漏回调对象会浪费内存。
替代方案:C 包装函数
对于复杂的集成,使用轻量的 C 适配层可能比 FFI 回调更简洁。适配层通过 C API 回调 Lua,从而可以完全控制协程和错误处理。
性能
FFI 回调速度很快,但不如直接的 FFI 调用,因为 C 到 Lua 的桥接需要额外的准备开销。对于非常高频的回调(例如音频处理),可以考虑使用纯 C 实现。
回调问题
为什么必须保留对 FFI 回调对象的 Lua 引用?
回顾:FFI 回调
使用 ffi.cast("fn_ptr_type", luaFunc) 创建兼容 C 的回调。请始终保存一个引用,以防止垃圾回收。回调不能执行 yield。请使用上值将上下文传入回调。
常见问题解答
「回调:将 Lua 函数传递给 C」课时是免费的吗?
是的 — 「回调:将 Lua 函数传递给 C」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Lua Academy 课程的其余内容,请升级到 CoddyKit PRO。 Lua Academy 课程共包含 4 节课。
「回调:将 Lua 函数传递给 C」这节课中我会学到什么?
使用 ffi.cast 创建可回调 Lua 代码的 C 回调函数。 你通过在浏览器中直接运行的动手代码来练习 Lua Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Lua Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Lua Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「回调:将 Lua 函数传递给 C」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Lua Academy 课中编写并运行代码吗?
能。每节 Lua Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- FFI 基础:ffi.cdef 和 ffi.load
- 通过 FFI 调用 C 函数
- FFI 中的指针、结构体和数组
- 回调:将 Lua 函数传递给 C