malcolm-ffi at cs.york.ac.uk
malcolm-ffi at cs.york.ac.uk
Tue Nov 28 07:00:14 EST 2000
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)
> I believe that this stuff belongs into the higher-level
> marshalling library.
> 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
> > ----------------------------------------------------------------
> > -- 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
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
More information about the FFI