Simon Marlow <simonmar@microsoft.com> wrote,
The main concern as far as adding functionality to the marshalling libraries seems to be the need to separate the compiler-dependent primitives from the rest of the library. With that in mind, I'll propose the following changes:
* Deprecate everything in Storable except the class itself and its instances.
* Add the Marshal module below (the names are of course all up for discussion, including the name of the module itself).
The implementation of Marshal is compiler independent, except there's a requirement for a way to convert an errno value into an IOError. As noted below, perhaps the error processing, or at least the compiler-dependent portion, should be farmed off into another module.
I omitted some of the generic utilities from Marcin's proposal, since while obviously useful they don't seem to belong here.
------------------------------------------------------------------------ -- Allocation, deallocation and marshalling for objects and arrays
malloc, -- :: Storable a => IO (Ptr a) mallocArray, -- :: Storable a => Int -> IO (Ptr a) mallocBytes, -- :: Int -> IO (Ptr a)
alloca, -- :: Storable a => (Ptr a -> IO b) -> IO b allocaArray, -- :: Storable a => Int -> (Ptr a -> IO b) -> IO b allocaBytes, -- :: Int -> (Ptr a -> IO b) -> IO b
reallocArray, -- :: Storable a => Ptr a -> Int -> IO (Ptr a) reallocBytes, -- :: Ptr a -> Int -> IO (Ptr a)
free -- :: Ptr a -> IO ()
pokeArray, -- :: Storable a => Ptr a -> [a] -> IO () pokeArray0, -- :: Storable a => a -> Ptr a -> [a] -> IO ()
peekArray, -- :: Storable a => Ptr a -> Int -> IO [a] peekArray0, -- :: (Storable a, Eq a) => a -> Ptr a -> IO [a]
withObject, -- :: Storable a => a -> (Ptr a -> IO b) -> IO b withArray, -- :: Storable a => [a] -> (Ptr a -> IO b) -> IO b withArray0, -- :: Storable a => a -> [a] -> (Ptr a -> IO b) -> IO b
new, -- :: Storable a => a -> IO (Ptr a) newArray, -- :: Storable a => [a] -> IO (Ptr a) newArray0, -- :: Storable a => a -> [a] -> IO (Ptr a)
---------------------------------------------------------------- -- Haskellish interface to memcpy and memmove.
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 ()
[..]
------------------------------------------------------------------------ ----- -- Misc indexPtr -- :: Storable a => Ptr a -> Int -> Ptr a )
These are fine with me.
------------------------------------------------------------------ -- Error handling.
-- Perhaps these should be moved to another module (PosixError?)
getErrno, -- :: IO Int throwIf, -- :: (a -> Bool) -> String -> IO a -> IO a throwIf_EINTR, -- :: (a -> Bool) -> String -> IO a -> IO a throwIfNull, -- :: String -> IO (Ptr a) -> IO (Ptr a) throwIfNull_EINTR, -- :: String -> IO (Ptr a) -> IO (Ptr a) throwIfMinus1, -- :: Num a => String -> IO a -> IO a throwIfMinus1_EINTR, -- :: Num a => String -> IO a -> IO a throwCError, -- :: String -> Int -> IO a throwErrno, -- :: String -> IO a
IMHO, they should go into another module. `PosixError' seems reasonable. Moreover, the first set of functions should be re-exported by `Foreign' (which re-exports all the language independent low-level FFI). Not so, PosixError, which isn't part of `Foreign' (like CTypes isn't). And because the greatest fun of all is to argue about names, I propose to rename `throwIf_EINTR', `throwIfNull_EINTR', and `throwIfMinus1_EINTR' to `throwIfEINTR', `throwIfNullEINTR', and `throwIfMinus1EINTR', respectively. For GHC, we should specify Qrczak's requirement that errno is thread local. Finally, I am not sure whether we should really call the module `Marshal', because that would have been the name that I would have given the main interface to the higher-level marshalling module. How about `MarshalUtils' (following the subject of this thread)? Cheers, Manuel