I've recently found that it's possible to register a callback to a dynamically
loaded library and invoke it.
For example:
# test0.nim
# nim c --app:lib --noMain test0.nim
var registered: proc(p: ptr int) {.nimcall.}
proc registerFn(fn: proc(p: ptr int) {.nimcall.}) {.exportc, dynlib,
nimcall.} =
registered = fn
proc invokeWith(p: ptr int) {.exportc, dynlib, nimcall.} =
registered(p)
Run
# test1.nim
proc initModuleTest0() {.importc: "NimMain", cdecl, dynlib:
"./libtest0.so".}
proc registerFn(fn: proc(p: ptr int) {.nimcall.}) {.importc, nimcall,
dynlib: "./libtest0.so".}
proc invokeWith(p: ptr int) {.importc, nimcall, dynlib: "./libtest0.so".}
proc f(p: ptr int) =
inc(p[])
var x = 0
initModuleTest0()
registerFn(f)
invokeWith(x.addr)
echo x
Run
(I know such code currently have multi-GC problem with `refc`, because I'm not
using `-d:useNimrtl` and both the main program and the library have GCs.)
Anyway, I think the main program can serve as the role `nimrtl` usually has, by
registering GC-related callbacks to libraries being loaded, using this
technique, and thus avoid to have multi-GC.
As ORC has become the default strategy and doesn't have the multi-GC problem,
such problem has become less important, I think.