FFI Report, CVS Id 1.11

Simon Marlow simonmar at microsoft.com
Tue Aug 21 11:45:55 EDT 2001

> Further additions to the FFI
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> IMHO, the FFI should really be self-contained and not rely
> on other non-standardised extensions/libraries.  Therefore,
> I propose some additions.

This makes me slightly uneasy because the FFI specification will
conflict with the new library specification that is currently evolving.
For example, the names of all the modules are different (eg. CForeign ->
Foreign.C).  Now, the FFI spec is clearly much further along than the
library spec, so I don't want to hold it up, but I think it would be
useful if we could agree on what direction we want to go.  

My suggestion is that, since the new library spec will hopefully be
adopted by NHC, Hugs and GHC, that the FFI and library proposals may
co-exist and agree on the specification of the FFI modules.  That means
changing the FFI spec at a later date to accomodate the changes made as
a result of the library reorganisation.

> * I think, we should include the `Bits' module (or something
>   similar).  It is needed, eg, to handle bindings to C
>   functions that expect bit vectors as arguments.  
> * To implement marshalling for foreign imported pure
>   functions, `unsafePerformIO' is essential.  We could add
>   it to the module `Foreign' or `MarshalUtils'.  This raises
>   the question of whether `unsafeInterleaveIO' falls in the
>   same category.  I think, we should add `unsafePerformIO'
>   and leave `unsafeInterleaveIO' our as it is less important
>   for the FFI.

ok, but note that there will be some overlap with the library spec.

> * I am also not really convinced about
>   `MarshalUtils.withMany'.  There may be situations, where
>   such a function is handy, but should it really be in the
>   standard libraries?  Moreover, it isn't really marshalling
>   specific - it is JAFL (Just Another Function on Lists).

We can move it to Data.List.withMany in the new library hierarchy.

> Names
> ~~~~~
> * I don't think `CTypesISO' is a good name.  Maybe
>   `CTypesLib' as it contains the types from the C library
>   (as opposed to the normal builtin types)?  Or put it all
>   into `CTypes' after all - that doesn't mean GHC (or any
>   other compiler) has to put it into a single module, just
>   for the definition.  I tend to having one module only.

One module is fine with me.

I have a couple of other points:


Why do we still allow ForeignPtr as an argument to a foreign imported
function, now that we have withForeignPtr?  Is it just for convenience?
If that's the case, it would be enlightening for the spec to say so
(perhaps in a footnote).


One thing that bugs me about writing FFI code at the moment is that
there isn't a portable way to generate an IOError except through
CError.throwErrno and friends.  There's also no way to change the info
(location, filename, handle) in an existing IOError.  This is the single
cause of non-portability in a lot of the FFI code I've written recently.

Also, we currently can't provide a portable version of CError.hs.

I'd like to see something like this:

data IOErrorType -- abstract
mkIOError :: IOErrorType
	    -> String
          -> Maybe FilePath
          -> Maybe Handle
	    -> IOError

alreadyExistsError :: IOErrorType
alreadyInUseError  :: IOErrorType

addIOErrorLoc        :: String             -> IO a -> IO a
addIOErrorLocAndPath :: String -> FilePath -> IO a -> IO a

This doesn't require any more functionality than is already required by
Haskell 98 (although perhaps the range of IOErrorType could be expanded
somewhat), and it should sit just as well on top of Nhc's implementation
of IOErrors as GHC's.  Furthermore it would let us provide a portable
implementation of CError.hs.

The addIOError functions are very useful.  Quite often an error is
generated by throwErrno in a function which is a long way from the one
which the consumer of a library initially called; for example when I get
an error from Directory.renameFile I want the error message to say
"Directory.renameFile" and contain the filename that I passed to
renameFile.  So you'd implement renameFile as

renameFile file1 file2 = 
  addIOErrorLocAndPath "Directoy.renameFile" file1 $ do


More information about the FFI mailing list