Hello friends I'm wrapping a small C library for hooking APIs and it ends up having a method like this:
proc subhook_new*(src: pointer; dst: pointer; flags: subhook_flags_t = subhook_flags.NONE): subhook_t {.importc, cdecl, impsubhookHdr.}
So I need to end up passing it two pointers to procs. I've got a small example where I'm attempting to hook my own method from Nim:
import strformat
import dependencies/subhook
type addProc = proc(a, b: uint32): uint32 {.cdecl.}
var add_hook: subhook_t
proc add(a, b: uint32): uint32 {.cdecl.} =
result = a + b
echo &"Add: {a} + {b} = {result}\n"
proc newAdd(a, b: uint32): uint32 {.cdecl.} =
echo "You've been hooked my guy!!"
let
newA = a + 10
newB = b + 10
# Call the original method after we've done our extra work
let trampoline = subhook_get_trampoline(add_hook)
if trampoline == nil:
raise newException(Exception, "Trampoline not found! Likely a disassembly issue")
cast[addProc](trampoline)(newA, newB)
# We have to pass the procs into here so we can cast them to pointers without
# nim freaking out
proc hookAdds(a, b: addProc) =
add_hook = subhook_new(cast[pointer](a), cast[pointer](b))
discard subhook_install(add_hook)
proc main() =
hookAdds(add, newAdd)
discard add(1, 1)
discard subhook_remove(add_hook)
subhook_free(add_hook)
if isMainModule:
main()
This is working however I'd like to have a better way to call it. Why can I not cast[pointer](add) from main()? And how could I have a hook method that's generic without having to define the proc type?
Do you want a pointer to a proc or to type-erase your proc as a pointer?
For the last case, I don't see why cast[pointer](a) wouldn't work, I use this extensively: https://github.com/mratsim/photon-jit/blob/ef19544/photon_jit/photon_types.nim#L91-L93
and also for type-erasing functions in schedulers.
I'm attempting to type-erase a proc as a pointer.
In my second example you can't even do:
let a = add
Nim says invalid type: 'None' for let
You can also disambiguate overloaded procs via a type conversion:
let a = addProc(add)