Linux shared library in Nim - LS554/Code-Snippets GitHub Wiki
Shared libraries allow for code to be shared accross programmes and sytem wide. They are the Linux equivalent of DLLs.
The library
The library file (.so) provides the code that will be shared to other programmes.
proc NimMain() {.cdecl, importc.} # Sets up the Nim runtime, must be called before using any Nim code in a shared library context
proc library_init(): cint {.exportc, dynlib, cdecl.} =
NimMain() # Initializes the library
echo "Library initialized!"
return 0 # Return isn't needed but useful if you want to pass this result to the caller
proc library_main(arg: cint): cint {.exportc, dynlib, cdecl.} =
echo "We got the argument from the caller: ", arg # Prints the argument passed by the calling programme
echo "Done main!"
return 0 # This will be automatically converted to a cint and passed to the caller
proc library_deinit(): cint {.exportc, dynlib, cdecl.} =
echo "Cleaning up." # We don't have any global memory, so there's nothing to do
GC_FullCollect() # Force a full garbage collection
return 0 # Return isn't needed but useful if you want to pass this result to the callerFullCollect()
- Library code adapted from Peter's DevLog
Calling the library
While the library contains our main code, its useless on it's own. We need a programme to call it ~
# Declare the procedures from the library so we can call them:
proc library_init() {.cdecl, importc, dynlib: "lib.so".}
proc library_main(arg: cint): cint {.cdecl, importc, dynlib: "lib.so".}
proc library_deinit() {.cdecl, importc, dynlib: "lib.so".}
# Run the code from the library:
when isMainModule:
library_init() # Initialize the library
let result = library_main(42) # The return value of the library's main procedure
echo "Result: ", result # This prints the return value passed from the library's main procedure
library_deinit() # Deinitialize the library
Finishing up
To compile the library, we will specify it's type as a library, and it's output. Remember the caller will call the library by it's name, so if you change it's output you must update this in the caller's source code.
nim c --app:lib --out:lib.so lib.nim
To compile the caller, we need to tell the compiler to look for our library. We hard-code this in at compile time, so make sure the library is not moved or the caller won't find it!
nim c --passL:"-Wl,-rpath,." caller.nim
The -rpath flag specifies the library's location to the linker. Since both files are in the same directory, we use "." . If your library is in a different directory, for example "lib", update the command accordingly:
nim c --passL:"-Wl,-rpath,./lib" caller.nim
Note: Since it is being specified here, you shouldn't have to update the caller's code. Just ensure the file name still matches!