OK, so here comes another weird question from lol.
I've been experimenting with dynamic/shared libraries and calling it different symbols/functions.
Let's take this as an example:
Library
# nim c -d:release --app:lib testlib.nim
{.push dynlib exportc.}
proc doIt*() =
echo "I'm doing it!"
proc doSomething*(a: int):cstring =
echo "I'm doing something"
echo "from the library"
echo "a: " & $(a)
return "booom!"
proc doSomethingElse*(a: cstring):cstring =
echo "I'm doing something else"
echo "from the library"
echo "a: " & $(a)
return 2
proc doubleIt*(b: int):int =
return b*2
{.pop.}
Main loader
# nim c -d:release loader.nim
import dynlib
type
getVoid_returnVoid = proc() {.nimcall.}
getInt_returnString = proc(a: int):cstring {.nimcall.}
getString_returnString = proc(a:cstring):cstring {.nimcall.}
getInt_returnInt = proc(a:int):int {.nimcall.}
when isMainModule:
let lib = loadLib("libtestlib.dylib")
if lib == nil:
echo "Could not load given library. Quitting..."
quit(QuitFailure)
let doIt = cast[getVoid_returnVoid](lib.symAddr("doIt"))
let doSomething = cast[getInt_returnString](lib.symAddr("doSomething"))
let doSomethingElse = cast[getString_returnString](lib.symAddr("doSomethingElse"))
let doubleIt = cast[getInt_returnInt](lib.symAddr("doubleIt"))
if (doIt==nil or doSomething==nil or doSomethingElse==nil or doubleIt==nil):
echo "Could not find given symbols. Quitting..."
quit(QuitFailure)
doIt()
echo "got: " & $(doSomething(3))
echo "got: " & doSomethingElse("Hello world!")
echo "got: " & $(doubleIt(5)) # => 10
unloadLib(lib)
OK, so... after all this introduction, let me point out that the above works great.
Now... here's my issue: given the way I approach it above we obviously have to know what to cast each symbol to beforehand. What if the user - for example - gives us the details about what symbol X takes and returns?
I guess I could solve this with a huge list of if-else's or case/of statements and an endless list of all the possible combinations of proc types defined.
But it obviously sounds a bit messy.
Is there any way I could cast this lib.symAddr to something more generic, but customizeable? (let's say, it's the user who tells us that it get a string and returns an int - how would that be implemented?)