FFI Report, CVS Id 1.11

Manuel M. T. Chakravarty chak at cse.unsw.edu.au
Thu Aug 30 11:29:34 EDT 2001

"Simon Marlow" <simonmar at microsoft.com> wrote,

> > 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.

The main problem here is the naming of FFI library modules,
isn't it?  Isn't that to a certain extent not the same for
the H98 Standard Libraries?  I am not keen on depending on
the library spec (and its implementation) at the moment.
However, we may put into the appendix the names that we
expect the modules to take under the new library spec.
Would that be ok?

> > * 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.

Re Bits: As long as it is the same module Bits that FFI and
  library spec refer to, it shouldn't be a problem.

Re unsafePerformIO: Foreign would export the name, but where
  it comes from doesn't matter.  Under the library spec, I
  would expect Foreign to just re-export that name.

This way should be ok, shouldn't we?

> > * 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.

I would be more comfortable with it being in a List library.

> ForeignPtr
> ~~~~~~~~~~
> 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).

I am the wrong person to ask.  I was always against having
`ForeignPtr's as arguments to foreign imported functions.
And they make for an ugly exception in the definition of the
types allowed in the signature for foreign imports.

Unless, there are serious objections, I'll remove them from
the list of types that are allowed in foreign function

> IOError
> ~~~~~~~
> 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.

Yes, this bugs me, too.

> 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.

Malcolm?  Agreed?

> 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
>    ...

I understand what you want to achieve, but I am not really
sure yet that it the right way.  Basically, you propose to
maintain an implicit state that stores information that
should go into the next error message, right?  Can't this
lead to unexpected results unless everybody is very
disciplined about how to use this feature.  Especially, when
a function has more than one potential failure point, I am
concerned that the context may be misleading.


More information about the FFI mailing list