summary refs log tree commit diff stats
path: root/lib/system/dyncalls.nim
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2009-06-08 08:06:25 +0200
committerAndreas Rumpf <rumpf_a@web.de>2009-06-08 08:06:25 +0200
commit4d4b3b1c04d41868ebb58bd9ccba7b303007e900 (patch)
tree909ed0aad0b145733521f4ac2bfb938dd4b43785 /lib/system/dyncalls.nim
parentce88dc3e67436939b03f97e624c11ca6058fedce (diff)
downloadNim-4d4b3b1c04d41868ebb58bd9ccba7b303007e900.tar.gz
version0.7.10
Diffstat (limited to 'lib/system/dyncalls.nim')
-rw-r--r--lib/system/dyncalls.nim124
1 files changed, 124 insertions, 0 deletions
diff --git a/lib/system/dyncalls.nim b/lib/system/dyncalls.nim
new file mode 100644
index 000000000..c0371d069
--- /dev/null
+++ b/lib/system/dyncalls.nim
@@ -0,0 +1,124 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2009 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+# This file implements the ability to call native procs from libraries.
+# It is not possible to do this in a platform independant way, unfortunately.
+# However, the interface has been designed to take platform differences into
+# account and been ported to all major platforms.
+
+type
+  TLibHandle = pointer       # private type
+  TProcAddr = pointer        # libary loading and loading of procs:
+
+const
+  NilLibHandle: TLibHandle = nil
+
+proc nimLoadLibrary(path: string): TLibHandle {.compilerproc.}
+proc nimUnloadLibrary(lib: TLibHandle) {.compilerproc.}
+proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr {.compilerproc.}
+
+proc nimLoadLibraryError(path: string) {.compilerproc, noinline.} =
+  raise newException(EInvalidLibrary, "could not load: " & path)
+
+# this code was inspired from Lua's source code:
+# Lua - An Extensible Extension Language
+# Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil
+# http://www.lua.org
+# mailto:info@lua.org
+
+when defined(posix):
+  #
+  # =========================================================================
+  # This is an implementation based on the dlfcn interface.
+  # The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD,
+  # NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least
+  # as an emulation layer on top of native functions.
+  # =========================================================================
+  #
+
+  # c stuff:
+  var
+    RTLD_NOW {.importc: "RTLD_NOW", header: "<dlfcn.h>".}: int
+
+  proc dlclose(lib: TLibHandle) {.importc, header: "<dlfcn.h>".}
+  proc dlopen(path: CString, mode: int): TLibHandle {.
+      importc, header: "<dlfcn.h>".}
+  proc dlsym(lib: TLibHandle, name: cstring): TProcAddr {.
+      importc, header: "<dlfcn.h>".}
+
+  proc nimUnloadLibrary(lib: TLibHandle) =
+    dlclose(lib)
+
+  proc nimLoadLibrary(path: string): TLibHandle =
+    result = dlopen(path, RTLD_NOW)
+
+  proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr =
+    result = dlsym(lib, name)
+
+elif defined(windows) or defined(dos):
+  #
+  # =======================================================================
+  # Native Windows Implementation
+  # =======================================================================
+  #
+  type
+    THINSTANCE {.importc: "HINSTANCE".} = pointer
+
+  proc FreeLibrary(lib: THINSTANCE) {.importc, header: "<windows.h>", stdcall.}
+  proc winLoadLibrary(path: cstring): THINSTANCE {.
+      importc: "LoadLibraryA", header: "<windows.h>", stdcall.}
+  proc GetProcAddress(lib: THINSTANCE, name: cstring): TProcAddr {.
+      importc: "GetProcAddress", header: "<windows.h>", stdcall.}
+
+  proc nimUnloadLibrary(lib: TLibHandle) =
+    FreeLibrary(cast[THINSTANCE](lib))
+
+  proc nimLoadLibrary(path: string): TLibHandle =
+    result = cast[TLibHandle](winLoadLibrary(path))
+
+  proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr =
+    result = GetProcAddress(cast[THINSTANCE](lib), name)
+
+elif defined(mac):
+  #
+  # =======================================================================
+  # Native Mac OS X / Darwin Implementation
+  # =======================================================================
+  #
+  {.error: "no implementation for dyncalls yet".}
+
+  proc nimUnloadLibrary(lib: TLibHandle) =
+    NSUnLinkModule(NSModule(lib), NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES)
+
+  var
+    dyld_present {.importc: "_dyld_present", header: "<dyld.h>".}: int
+
+  proc nimLoadLibrary(path: string): TLibHandle =
+    var
+      img: NSObjectFileImage
+      ret: NSObjectFileImageReturnCode
+      modul: NSModule
+    # this would be a rare case, but prevents crashing if it happens
+    result = nil
+    if dyld_present != 0:
+      ret = NSCreateObjectFileImageFromFile(path, addr(img))
+      if ret == NSObjectFileImageSuccess:
+        modul = NSLinkModule(img, path, NSLINKMODULE_OPTION_PRIVATE or
+                                        NSLINKMODULE_OPTION_RETURN_ON_ERROR)
+        NSDestroyObjectFileImage(img)
+        result = TLibHandle(modul)
+
+  proc nimGetProcAddr(lib: TLibHandle, cname: string): TProcAddr =
+    var
+      nss: NSSymbol
+    nss = NSLookupSymbolInModule(NSModule(lib), name)
+    result = TProcAddr(NSAddressOfSymbol(nss))
+
+else:
+  {.error: "no implementation for dyncalls".}