Docs / One-target hooking (OTH)

One-target hooking (OTH)

Stack multiple hooks on a single C closure — later hooks can chain into earlier ones.

Library#23 of 23 Functions5
oth.hook(target: function, hook: function) → function
Install a hook on target (must be a C closure). Multiple hooks can be stacked on the same target. Returns a callable that dispatches to the next hook in the chain (or the original if you're the last hook). Call it explicitly inside your hook to continue the chain — otherwise your hook's return value becomes the final result.
lua
local orig
orig = oth.hook(print, function(...)
    orig("HOOKED:", ...)
end)
print("hi")   --> HOOKED: hi
oth.unhook(target: function, hook: function) → boolean
Remove a specific hook. true if it was found and removed. The chain rebuilds; when no hooks remain, the target's original C function is restored.
lua
local myHook = function() end
oth.hook(target, myHook)
oth.unhook(target, myHook)   --> true
oth.restore(target: function) → boolean
Drop every hook on the target and restore its original C function.
lua
oth.restore(print)   -- undo any oth hooks on print
oth.ishooked(target: function) → boolean
true if the target currently has any OTH hooks installed.
lua
print(oth.ishooked(print))  --> false / true
oth.get_root_callback(target: function) → function?
Returns a wrapper that calls the target's original (pre-hook) C function directly. Same as the second value returned by oth.hook for the very first hook installed.
lua
local rawPrint = oth.get_root_callback(print)
rawPrint("bypass all hooks")
lua
-- Chain two hooks on the same target.
local h1 = oth.hook(target, function(...)
    print("hook 1 fired")
    return h1(...)   -- forward to hook 2 (or original)
end)

local h2 = oth.hook(target, function(...)
    print("hook 2 fired")
    return h2(...)   -- forward to original
end)

target(1, 2, 3)
-- prints: hook 2 fired, hook 1 fired

oth.unhook(target, h2)   -- pop hook 2 off the chain
oth.restore(target)      -- remove all hooks