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