Let's get this finished
Sven Panne
Sven.Panne at informatik.uni-muenchen.de
Fri Jan 5 18:24:14 EST 2001
I think we all agree now that malloc & friend can be written in H98 +
FFI, so the only question is how they should be implemented in
hslibs. The variant which uses local definitions instead of pattern
type signatures is nicer IMHO because it *is* H98 and given GHC's
optimizations, it doesn't make any performance difference. In general
we should make hslibs as H98-conforming as possible and remove most
GHCisms. For performance there's always #ifdef (well, at least if we
consider piping Haskell sources through cpp as "standard"/H98).
Manuel's MarshalXXX family look nice, but I'd like to summarize what
exactly should go into what module, marking places which probably need
more thoughts/discussions with `!!!!!':
-- MarshalAlloc ------------------------------------------------------
malloc :: Storable a => IO (Ptr a)
mallocBytes :: Int -> IO (Ptr a)
alloca :: Storable a => (Ptr a -> IO b) -> IO b
allocaBytes :: Int -> (Ptr a -> IO b) -> IO b
reallocBytes :: Ptr a -> Int -> IO (Ptr a)
free :: Ptr a -> IO ()
-- MarshalArray ------------------------------------------------------
mallocArray :: Storable a => Int -> IO (Ptr a)
mallocArray0 :: Storable a => Int -> IO (Ptr a)
allocaArray :: Storable a => Int -> (Ptr a -> IO b) -> IO b
allocaArray0 :: Storable a => Int -> (Ptr a -> IO b) -> IO b
reallocArray :: Storable a => Ptr a -> Int -> IO (Ptr a)
reallocArray0 :: Storable a => Ptr a -> Int -> IO (Ptr a)
!!!!! The current MarshalUtils uses
!!!!! peekArray :: Storable a => Ptr a -> Int -> IO [a]
!!!!! but the signature below looks more consistent with peekArray0:
peekArray :: Storable a => Int -> Ptr a -> IO [a]
peekArray0 :: (Storable a, Eq a) => a -> Ptr a -> IO [a]
pokeArray :: Storable a => Ptr a -> [a] -> IO ()
pokeArray0 :: Storable a => a -> Ptr a -> [a] -> IO ()
withArray :: Storable a => [a] -> (Ptr a -> IO b) -> IO b
withArray0 :: Storable a => a -> [a] -> (Ptr a -> IO b) -> IO b
newArray :: Storable a => [a] -> IO (Ptr a)
newArray0 :: Storable a => a -> [a] -> IO (Ptr a)
-- MarshalString -----------------------------------------------------
!!!!! I'm with Marcin here: Let's keep things simple and do not
!!!!! provide an opaque type CString here. We can't guess all
!!!!! possible uses, so a type synonym would be the right thing
!!!!! here. Using a pointer/length combo is quite common, too,
!!!!! so this deserves another type synonym. Note that some
!!!!! functions below look a bit strange, but symmetry rulez! :-)
!!!!! Charset conversions are a diff{erent,icult} story and should
!!!!! be handled by a separate module, so only the well-known
!!!!! ignore-the-upper-half variants are given here.
type CString = Ptr CChar
type CStringLen = (CString, Int)
mallocCString :: String -> IO CString
mallocCStringLen :: String -> IO CStringLen
peekCString :: CString -> IO String
peekCStringLen :: CStringLen -> IO String
pokeCString :: CString -> String -> IO ()
pokeCStringLen :: CStringLen -> String -> IO ()
withCString :: String -> (CString -> IO a) -> IO a
withCStringLen :: String -> (CStringLen -> IO a) -> IO a
newCString :: String -> IO CString
newCStringLen :: String -> IO CStringLen
-- MarshalError ------------------------------------------------------
!!!!! Haven't thought very deeply about this, but Marcin's QErrors
!!!!! probably looks OK after a little polishing (use strerror,
!!!!! provide a more complete throwXXX family, ...). And remember:
!!!!! errno *is* a thread-local thing. :-)
-- MarshalConv -------------------------------------------------------
!!!!! I can't see a compelling reason for this module, neither what
!!!!! exactly should belong here. ISO C defines a mapping to 0/1,
!!!!! which can easily be captured by fromBool/toBool (in MarshalUtils
!!!!! below). Maybe is handled there, too.
-- MarshalUtils ------------------------------------------------------
fromBool :: Num a => Bool -> a
fromBool = fromIntegral . fromEnum
toBool :: Num a => a -> Bool
toBool = (/= 0)
withObject :: Storable a => a -> (Ptr a -> IO b) -> IO b
new :: Storable a => a -> IO (Ptr a)
!!!!! Example usages:
!!!!! do ...
!!!!! mbInt <- maybeNull peek ptr1
!!!!! mbString <- maybeNull peekCString ptr2
!!!!! .....
!!!!! maybeNothing withObject Nothing $ \ptr -> ...
!!!!! maybeNothing withCString (Just "foo!") $ \ptr -> ...
!!!!!
!!!!! Does anybody have better names for these two functions?
!!!!! They sound OK for me, but I'm not a native speaker...
maybeNull :: (Ptr a -> IO b) -> Ptr a -> IO (Maybe b)
maybeNull f ptr | ptr == nullPtr = return Nothing
| otherwise = liftM Just $ f ptr
maybeNothing :: (a -> (Ptr b -> IO c) -> IO c) -> (Maybe a -> (Ptr b -> IO c) -> IO c)
maybeNothing = maybe ($ nullPtr)
copyArray :: Storable a => Ptr a -> Ptr a -> Int -> IO ()
copyBytes :: Ptr a -> Ptr a -> Int -> IO ()
moveArray :: Storable a => Ptr a -> Ptr a -> Int -> IO ()
moveBytes :: Ptr a -> Ptr a -> Int -> IO ()
!!!!! Do we really need this?
indexPtr :: Storable a => Ptr a -> Int -> Ptr a
As Manuel already wrote it's a good idea to leave C2HS's marshX
routines out and to re-export all the modules above, but should this
be done via a new module Marshal or should Foreign do this? Should
Marshal re-export Foreign or vice-versa? Hmmm...
And just a final topic which really should be settled:
"Marshal" or "Marshall"?? :-}
Cheers,
Sven
More information about the FFI
mailing list