qforeign-0.62

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)

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




More information about the FFI mailing list