For a "Pure Nim" plugin system use DLLs/SOs. You could do them like C with dlopen, etc.. or use Nim's dynlib module. Here's a small example..
# plugin.nim
var data = 0
{.push dynlib exportc.}
proc setup*(num:int) =
data = num
echo "Plugin Setup!"
proc getData*: int = data
{.pop.}
# app.nim
import dynlib
type
SetupProc = proc(num:int) {.nimcall.}
GetDataProc = proc(): int {.nimcall.}
proc testPlugin(path:string) =
let lib = loadLib(path)
if lib != nil:
let setupAddr = lib.symAddr("setup")
let getDataAddr = lib.symAddr("getData")
if setupAddr != nil and getDataAddr != nil:
let setup = cast[SetupProc](setupAddr)
let getData = cast[GetDataProc](getDataAddr)
setup(123)
echo "Plugin Data: ", getData()
unloadLib(lib)
testPlugin("./libplugin.so") # unix path
Compile & Run:
$ nim c --app:lib plugin
$ nim c -r app
Plugin Setup!
Plugin Data: 123
NOTE: This section in the Nim User-Guide mentions the need to generate and link against nimrtl.dll.. not sure if that's necessary for all Nim-created DLLs to work without GC/Memory bugs or something specific to using the Nim compiler itself as a DLL... (my example compiles and runs fine.. but that doesn't say much). Some clarity from someone more informed would be nice.