Preliminary support for dynamic libraries.
h3rald h3rald@h3rald.com
Sat, 28 Oct 2017 15:30:08 +0200
5 files changed,
22 insertions(+),
38 deletions(-)
M
dynamic/dynamicadd.nim
→
examples/dyntest.nim
@@ -1,11 +1,9 @@
## This is all you need to create a min module in Nim -## Compile with `nim c --app:lib --noMain -d:release dynamicadd.nim` -include mindyn +## Compile with `nim c --app:lib --noMain -d:release -l:"-undefined dynamic_lookup" dyntest.nim` -proc setup*(): DynInfo {.rtl.} = - result = DynInfo(moduleName: "the_lib", dynlibVersion: 1) +include ../mindyn -proc the_lib*(i: In) {.rtl.} = +proc dyntest*(i: In) {.rtl, dynlib, exportc.} = let def = i.define() def.symbol("myp") do (i: In): let vals = i.expect("num", "num")@@ -21,4 +19,4 @@ if b.isFloat:
i.push newVal(a.floatVal + b.floatVal) else: i.push newVal(a.floatVal + b.intVal.float) - def.finalize("dyn") + def.finalize("dyntest")
M
dynamic/mindyn.nim
→
mindyn.nim
@@ -145,7 +145,7 @@ proc typeName*(v: MinValue): string {.importc, extern:"typeName_81jMzzfB0Qc0O4DsVU5arg".}
proc isSymbol*(s: MinValue): bool {.importc, extern:"isSymbol_BKcj9aQlJC73fcAZURf0pHw".} proc isQuotation*(s: MinValue): bool {.importc, extern:"isQuotation_BKcj9aQlJC73fcAZURf0pHw_2".} proc isString*(s: MinValue): bool {.importc, extern:"isString_BKcj9aQlJC73fcAZURf0pHw_3".} -proc isFloat*(s: MinValue): bool {.importc, extern:"isFloat_BKcj9aQlJC73fcAZURf0pHw_4".} +proc isFloat*(s: MinValue): bool {.importc, extern:"isFloat_BKcj9aQlJC73fcAZURf0pHw_8".} proc isInt*(s: MinValue): bool {.importc, extern:"isInt_BKcj9aQlJC73fcAZURf0pHw_5".} proc isNumber*(s: MinValue): bool {.importc, extern:"isNumber_BKcj9aQlJC73fcAZURf0pHw_6".} proc isBool*(s: MinValue): bool {.importc, extern:"isBool_BKcj9aQlJC73fcAZURf0pHw_7".}
M
min.nim
→
min.nim
@@ -5,6 +5,7 @@ critbits,
parseopt2, strutils, os, + ospaths, json, sequtils, algorithm,@@ -136,42 +137,26 @@ i.eval MINRC.readFile()
i.eval "\"prompt\" unseal" type - DynInfo = object - moduleName: string # The name of the symbol to load and run - dynlibVersion: int # The version of the interface the dynlib is built for. This should increase if the interface changes - setupProc = proc(): DynInfo {.nimcall.} - libProc = proc( - i: In - ) {.nimcall.} + LibProc = proc(i: In) {.nimcall.} + proc dynLib*(i: In) = - var - dll: LibHandle - setup: setupProc - echo "Trying to load libraries from " & $(getAppDir() / "dynlibs") + info("Trying to load libraries from " & $(getAppDir() / "dynlibs")) for library in walkFiles(getAppDir() / "dynlibs/*"): - dll = loadLib(library) + var modname = library.splitFile.name + var libfile = library.splitFile.name & library.splitFile.ext + if modname.len > 3 and modname[0..2] == "lib": + modname = modname[3..modname.len-1] + let dll = library.loadLib() if dll != nil: - let setupAddr = dll.symAddr("setup") - if setupAddr != nil: - setup = cast[setupProc](setupAddr) - if setup != nil: - let - expectedVersion = 1 - libInfo = setup() - libAddr = dll.symAddr(libInfo.moduleName) - if libInfo.dynlibVersion == expectedVersion: - if libAddr != nil: - var lib = cast[libProc](libAddr) - i.lib - echo "Loaded dynlib " & libInfo.moduleName & "[" & library & "]" - else: - echo "Wasn't able to load " & libInfo.moduleName & "(i: In) from " & library - else: - echo "Dynlib in " & library & " has wrong version, got " & $libInfo.dynlibVersion & " but expected " & $expectedVersion + let modsym = dll.symAddr(modname) + if modsym != nil: + let modproc = cast[LibProc](dll.symAddr(modname)) + i.modproc() + info("[$1] Dynamic module loaded successfully: $2" % [libfile, modname]) else: - echo "Wasn't able to load setup() from " & library + warn("[$1] Library does not contain symbol $2" % [libfile, modname]) else: - echo "Unable to load lib from " & library + warn("Unable to load dynamic library: " & libfile) proc interpret*(i: In, s: Stream) = i.stdLib()