I am writing a .so shared library in Nim for a large C++ host program.
The host program calls a symbol init in my nim program and passes a pointer to the target function within the host program. The plugin calls the target function to perform initialization. In the real program, the target function receives the initialization data, but in this simplified implementation, it simply outputs a message to show it was called.
The host program first loads a .so file written in C++, then a .co file doing the same thing written in Nim.
https://gist.github.com/carlocapocasa/bd403a3c1b1bf12ab434d2d7154470e6
You may clone, build and run it to observe the effects:
git clone https://gist.github.com/bd403a3c1b1bf12ab434d2d7154470e6.git hostguest cd hostguest make LD_LIBRARY_PATH=. ./host
The output is this:
plugin.cpp: init host: target plugin.nim: init
This is strange- the host code calls the init function twice, once in plugin.cpp, and once in plugin.nim, but the target function only outputs once, for the C++ version.
Adding some code (not in the example), I found that the target function actually gets called by plugin.nim, but the stdout message is unexpectedly silenced.
Why could this be, and how could I keep this from happening?
Yeah that was pretty dumb- I guess I was a little confused there by all the new information, sorry.
The original non-simplified version didn't work for unrelated reasons: It appears that a missing in a struct full of function pointers seemed to throw off the memory addresses, causing some random address to be called, that by coincidence contained something that didn't do anything.
# bad
type
foo* {.bycopy.} = object
bar*: proc ()
fuz*: proc () # calling fooObject.fuz() points to the wrong address, either crashing or calling something else
# good
type
foo* {.bycopy.} = object
bar*: proc () {.cdecl.}
fuz*: proc () {.cdecl.} # this works
Then I simplified the thing and behaved the same, so...
For posterity, part of what I was missing was how to print function pointer addresses:
# echo function pointer from struct passed from C++
echo "fooObject.fuz: ", cast[cint](fooObject.fuz)