aboutsummaryrefslogtreecommitdiffhomepage
path: root/System/Posix/DynamicLinker.hsc
diff options
context:
space:
mode:
authorGravatar stolz <unknown>2003-05-16 06:41:27 +0000
committerGravatar stolz <unknown>2003-05-16 06:41:27 +0000
commitf4777ebff44f327edcda50de76dc848764278ca1 (patch)
treeeed4786edaa10661271da24f3107de6140235769 /System/Posix/DynamicLinker.hsc
parentd36da3716075fb5788321cf53bafb60965d3c4d7 (diff)
[project @ 2003-05-16 06:41:25 by stolz]
- move System.DL to System.Posix.DynamicLinker - take ownership There's a compiler warning when passing the 'const char*' result from dlerror() to peekCString (discarded qualifier). Does an FFI-expert know how to get rid of this warning?
Diffstat (limited to 'System/Posix/DynamicLinker.hsc')
-rw-r--r--System/Posix/DynamicLinker.hsc95
1 files changed, 95 insertions, 0 deletions
diff --git a/System/Posix/DynamicLinker.hsc b/System/Posix/DynamicLinker.hsc
new file mode 100644
index 0000000..6d13de5
--- /dev/null
+++ b/System/Posix/DynamicLinker.hsc
@@ -0,0 +1,95 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module : System.Posix.DynamicLinker
+-- Copyright : (c) Volker Stolz <vs@foldr.org> 2003
+-- License : BSD-style (see the file libraries/base/LICENSE)
+--
+-- Maintainer : vs@foldr.org
+-- Stability : provisional
+-- Portability : non-portable (requires POSIX)
+--
+-- Dynamic linker support through dlopen()
+-----------------------------------------------------------------------------
+
+module System.Posix.DynamicLinker (
+
+ module System.Posix.DynamicLinker.Prim,
+ dlopen,
+ dlsym,
+ dlerror,
+ dlclose,
+ withDL, withDL_,
+ undl,
+ )
+
+-- Usage:
+-- ******
+--
+-- Let's assume you want to open a local shared library \'foo\' (.\/libfoo.so)
+-- offering a function
+-- @char \* mogrify (char\*,int)@
+-- and invoke @str = mogrify("test",1)@:
+--
+--
+-- type Fun = CString -> Int -> IO CString
+-- foreign import dynamic unsafe fun__ :: FunPtr Fun -> Fun
+--
+-- withDL "libfoo.so" [RTLD_NOW] \$ \\ mod -> do
+-- funptr <- dlsym mod "mogrify"
+-- let fun = fun__ funptr
+-- withCString "test" \$ \\ str -> do
+-- strptr <- fun str 1
+-- strstr <- peekCString strptr
+-- ...
+--
+
+where
+
+#include "HsUnix.h"
+
+import System.Posix.DynamicLinker.Prim
+import IO ( bracket )
+import Control.Monad ( liftM )
+import Foreign.Ptr ( Ptr, nullPtr, FunPtr, nullFunPtr )
+import Foreign.C.String ( withCString, peekCString )
+
+dlopen :: String -> [RTLDFlags] -> IO DL
+dlopen path flags = do
+ withCString path $ \ p -> do
+ liftM DLHandle $ throwDLErrorIf "dlopen" (== nullPtr) $ c_dlopen p (packRTLDFlags flags)
+
+dlclose :: DL -> IO ()
+dlclose (DLHandle h) = throwDLErrorIf_ "dlclose" (== 0) $ c_dlclose h
+dlclose h = error $ "dlclose: invalid argument" ++ (show h)
+
+dlerror :: IO String
+dlerror = c_dlerror >>= peekCString
+
+-- |'dlsym' returns the address binding of the symbol described in @symbol@,
+-- as it occurs in the shared object identified by @source@.
+
+dlsym :: DL -> String -> IO (FunPtr a)
+dlsym source symbol = do
+ withCString symbol $ \ s -> do
+ throwDLErrorIf "dlsym" (== nullFunPtr) $ c_dlsym (packDL source) s
+
+withDL :: String -> [RTLDFlags] -> (DL -> IO a) -> IO a
+withDL mod flags f = bracket (dlopen mod flags) (dlclose) f
+
+withDL_ :: String -> [RTLDFlags] -> (DL -> IO a) -> IO ()
+withDL_ mod flags f = withDL mod flags f >> return ()
+
+-- |'undl' obtains the raw handle. You mustn't do something like
+-- @withDL mod flags $ liftM undl >>= \ p -> use p@
+
+undl :: DL -> Ptr ()
+undl = packDL
+
+throwDLErrorIf :: String -> (a -> Bool) -> IO a -> IO a
+throwDLErrorIf s p f = do
+ r <- f
+ if (p r)
+ then dlerror >>= \ err -> ioError (userError ( s ++ ": " ++ err))
+ else return r
+
+throwDLErrorIf_ s p f = throwDLErrorIf s p f >> return ()