Home

Awesome

dlutils

dlutils is a Nim package for easy shared library loading.

See package documentation.

Installing

$ nimble install dlutils

Configuration

Set -d=uselogging to turn logging on (via std/logging).

Usage

dlgencalls "somelib", paths:
  # proc and var definitions

dlgencalls creates three procs: proc open_somelib_library(): bool, proc close_somelib_library() and proc last_somelib_error().

Open proc

The open proc tries to load shared library defined in paths and loads all symbols defined in body. Paths may be either single string or an array of strings. Subsequent calls are ignored.

The open proc returns true on success or false on error (no library found, one of symbols not found).

Procs and variables marked with unchecked_ pragma do not cause open function to faile and are set to nil.

Allowed definitions in body:

Not allowed in body:

Allowed proc pragmas:

Allowed var pragmas:

All other proc/var pragmas are ignored.

Warning: Do not add ptr to variable type, it's done automatically (variable of type cint becomes ptr cint).

Close proc

The close proc unloads the shared library. All symbols loaded are set to nil. Subsequent calls are ignored.

Error proc

The error proc returns a human-readable string describing the most recent error that occured from a call to open_name_library() or empty string on no error.

The returned string does not include a trailing newline.

Example

Source:

import dlutils

# Create open_math_library, close_math_library, last_math_error
# and proc/var symbols defined in body.

dlgencalls "math", ["libm.so", "libm.so.6"]:
  # Required proc. open_math_library returns false if not found.
  proc cbrt (x: cdouble): cdouble

  # Optional proc. open_math_library sets sqrt to nil if not found.
  proc sqrt (x: cdouble): cdouble {.unchecked.}

  # Function "sqrtf" imported as "sqrt2".
  proc sqrt2 (x: cfloat): cfloat {.importc: "sqrtf".}

  # Required var of type ptr cint.
  var reqvar: cint

  # Optional var of type ptr clong.
  var optvar {.unchecked.}: clong

Generated Code:

var math_handle: LibHandle = nil

var cbrt*: proc (x, y: cdouble): cdouble {.cdecl, raises: [].} = nil
var sqrt*: proc (x, y: cdouble): cdouble {.cdecl, raises: [].} = nil
var sqrt2*: proc (x, y: cfloat): cfloat {.cdecl, raises: [].} = nil
var reqvar*: ptr cint = nil
var optvar*: ptr clong = nil

proc open_math_library*(): bool =
  result =
    ##  Open library.
    if math_handle == nil:
      math_handle = loadLib "libm.so"
      if math_handle == nil:
        return false
      cbrt = cast[cbrt.type](symAddr(math_handle, "cbrt"))
      if cbrt == nil:
        return false
      sqrt = cast[sqrt.type](symAddr(math_handle, "sqrt"))
      sqrt2 = cast[sqrt2.type](symAddr(math_handle, "sqrtf"))
      if sqrt2 == nil:
        return false
      reqvar = cast[reqvar.type](symAddr(math_handle, "reqvar"))
      if reqvar == nil:
        return false
      optvar = cast[optvar.type](symAddr(math_handle, "optvar"))
    true

proc close_math_library*() =
  ##  Close library.
  if math_handle != nil:
    cbrt = nil
    sqrt = nil
    sqrt2 = nil
    reqvar = nil
    optvar = nil
    math_handle.unloadLib
    math_handle = nil

proc last_math_error*(): string =
  ##  Returns the most recent error that occured from a call to open proc.
  #[
    code follows…
  ]#

Sample Code

import dlutils

# This dlgencalls will create two functions:
# - proc open_math_library(): bool
# - close_math_library()
dlgencalls "math", ["libm.so", "libm.so.6"]:
  # Required proc - open_math_library will fail (return false)
  # if not found.
  proc cbrt (x: cdouble): cdouble

  # Optional proc - sqrt will be nil if not found.
  proc sqrt (x: cdouble): cdouble {.unchecked.}

  # Required global variable (ptr cint) - open_math_library
  # will fail if not found.
  var reqvar: cint

  # Optional global variable (ptr clong) - optval will be set
  # to nil if not found.
  var optvar {.unchecked.}: clong

proc main() =
  if not open_math_library():
    echo "Failed to open library"
    quit QuitFailure

  defer:
    close_math_library()

  echo "cbrt(2.0) = ", cbrt 2.0

  if sqrt != nil:
    echo "sqrt(2.0) = ", sqrt 2.0

  echo "reqvar: ", reqvar[]

  if optval != nil:
    echo "optvar: ", optvar[]

when isMainModule:
  main()

License

dlutils is released under (either or both):