I have this driver code:
import dynlib
type myLibFunction = proc(): cstring {.nimcall.}
let lib = loadLib("library.dll")
let functionCallAddr = lib.symAddr("myStringFunction")
let libFunction = cast[myLibFunction](functionCallAddr)
echo libFunction()
And this library code:
# nim c -d:release --header --noMain --app:lib library.nim
proc internalStringFunction() : string =
"I'm a Nim String"
proc internalCStringFunction() : cstring =
"I'm a CString"
proc myStringFunction() : cstring {.exportc, cdecl, dynlib.} =
internalCStringFunction() # works
#"I'm a Nim String?" # works
#internalStringFunction() # doesn't work
#cstring(internalStringFunction()) # doesn't work
How do I expose the value of internalStringFunction to callers?
The error I get for the methods that don't work:
(most recent call last)
.\main.nim(9) main
SIGSEGV: Illegal storage access. (Attempt to read from nil?)
Error: execution of an external program failed: '.\main.exe
It looks like the issue is related to the way the DLL is compiled.
It works if I exclude --noMain, but I'm not sure why:
c -d:release --header --app:lib library.nim
It's normal, if you compile the DLL with --noMain then the function DllMain() is not created and the Nim system is not initializated calling NimMain() in DllMain() and the app crashes.
If you compile the DLL without --noMain it generates this initialization code and NimMain() is called when the OS calls DllMain():
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID lpvReserved)
{
if(fwdreason == DLL_PROCESS_ATTACH)
{
NimMain();
}
return 1;
}