Hi,
Is this a supported usecase: update global variables from a dynamic library? I understand in this simplified example, I can probably pass in As to add(). However in more complex applications, if the global variable can not be passed in, is there an alternative way to make this work?
types.nim
type
A* = ref object
name*: string
Add* = proc(a: A) {.nimcall.}
var As*: seq[A] = @[]
extension.nim
{.push dynlib exportc.}
import ./types
proc add*(a: A) =
As.add(a)
{.pop.}
main.nim
import dynlib
import ./types
var lib = load_lib("build/libextension.dylib")
var add = cast[Add](lib.sym_addr("add"))
add(A(name: "first"))
add(A(name: "second"))
assert As.len == 2 # This assertion fails
The code above can be cloned and run from https://github.com/gcao/test.nim
Thank you. Any suggestion on how to pass the context? Like below?
extension.nim
proc init*(<global variables>) =
...
main.nim
# load extension
var init = cast[Init](lib.sym_addr("init"))
init(<global variables>)
You can use the export statement to forward imported symbols: https://nim-lang.org/docs/manual.html#modules-export-statement
For example if you want extension.nim to forward types.nim to main.nim:
extension.nim:
{.push dynlib exportc.}
import ./types
export types # Importing `extension.nim` gives access to symbols in `types.nim`.
# You can also export individual symbols, for instance: `export As`.
proc add*(a: A) =
As.add(a)
{.pop.}
main.nim:
import dynlib, extension
# `types.nim` is now accessible through `extension.nim`.
var lib = load_lib("build/libextension.dylib")
var add = cast[Add](lib.sym_addr("add"))
echo add.repr
add(A(name: "first"))
add(A(name: "second"))
assert As.len == 2 # Asserts correctly.