Marcin proposes adding the following functions to the module Foreign:
peekCString :: Ptr CChar -> IO String peekCStringLen :: Ptr CChar -> Int -> IO String
withCString :: String -> (Ptr CChar -> IO a) -> IO a withCStringLen :: String -> (Ptr CChar -> Int -> IO a) -> IO a
newCString :: String -> IO (Ptr CChar) newCStringLen :: String -> IO (Ptr CChar, Int)
Manuel says
I believe that this stuff belongs into the higher-level marshalling library.
Simon says
I think Marcin is right in that C Strings are special (unfortunately). This interface seems reasonable, and simple. Do we have any objections?
I'm with Manuel. Module FFI/Foreign is already stable, and I object to adding things to it arbitrarily. By all means make a new module with these functions, which I can see could be useful. But please don't just allow "feature creep" over already-agreed specifications. Once these newer features are settled, I look forward to seeing a portable implementation.
---------------------------------------------------------------- -- Handling errors. Mostly conversion of errno to Haskell's IO -- exceptions.
-- Get the current value of C errno. getErrno :: IO Int
-- Throw an exception based on function name and given error code. throwCError :: String -> Int -> IO a -- Throw an exception based on function name and current errno -- value. Much more common than the above but less general, -- that's why there are two functions. throwErrno :: String -> IO a
Getting hold of error codes from C is a big hole in the current FFI that I agree needs to be plugged. Here's my contribution. I think we should use symbolic error codes in Haskell, like the `ENOENT' style in C. This is for portability, because as you may know, on different operating systems, symbolic names map to different ints. I would hate to see magic numbers like '35' on IRIX but '54' on SunOS appearing in code. In nhc98, we have an enumerated type data ErrNo = EPERM | ENOENT | ESRCH | EINTR | EIO | ENXIO | E2BIG | ENOEXEC | EBADF | ECHILD | .... deriving (Eq,Enum,Show) For some machines Eq is insufficiently strong, and the following kind of patch-up is required: eqErrNo :: ErrNo -> ErrNo -> Bool eqErrNo EWOULDBLOCK EAGAIN = True eqErrNo EAGAIN EWOULDBLOCK = True eqErrNo EDEADLOCK EDEADLK = True eqErrNo EDEADLK EDEADLOCK = True eqErrNo ENOTSUP EOPNOTSUPP = True eqErrNo EOPNOTSUPP ENOTSUP = True eqErrNo a b = a==b On other machines, derived Enum is not accurate either, due to discontinuities in the range, and as noted earlier, symbolic names can map to different ints. Finally, each individual operating system only actually recognises a (differing) subset of all the symbols that are possible. For these reasons, we need to generate the ErrNo module automatically for any given machine (auto-generator available on request), but the benefit is better code portability in Haskell. So I would suggest a refinement to Marcin's interface as follows:
getErrno :: IO ErrNo
implemented as (do i <- primGetErrNo return (toEnum i)) and a corresponding:
throwCError :: String -> ErrNo -> IO a
Regards, Malcolm