Minor tweaks to ffi addendum

Alastair Reid reid at cs.utah.edu
Sun Jun 2 13:42:06 EDT 2002

While implementing the full FFI for Hugs, I'm coming across a bunch of
little things that confuse me and some wee typos.  Here's a list of
what I've found so far.  If no-one objects in the next few days, I'll
go ahead and make minor changes to the report where required.

section 4.1.1:

  The definition of impents suggests that there must/can be spaces
  around the keywords 'dynamic' and 'wrapper' and that the static form
  can have spaces at start and end.  I'm going ahead and implementing
  this interpretation but want to remark that it seems a bit odd.

  No action proposed.

section 4.1.3:

  It took me a while to understand the explanation of Dynamic import.
  After a while, I realized that I should read the type as:

    (FunPtr ft) -> ft

  instead of 

    FunPtr (ft -> ft)

  The current text 'FunPtr ft -> ft' does mean the former but it 
  would be easier to read if written '(FunPtr ft) -> ft'.

  Proposed change: write the type as '(FunPtr ft) -> ft'

  Incidentally, how am I to interpret the type rules?
  Which of the following have the right type:

    foreign import ccall "dynamic" 
      mkFun1 :: FunPtr (Int -> IO ()) -> (Int -> IO ())

    type Int2 = Int
    foreign import ccall "dynamic" 
      mkFun2 :: FunPtr (Int2 -> IO ()) -> (Int -> IO ())

    newtype Int3 = Int3 Int
    foreign import ccall "dynamic" 
      mkFun3 :: FunPtr (Int3 -> IO ()) -> (Int -> IO ())

    data Int4 = Int4 Int
    foreign import ccall "dynamic" 
      mkFun4 :: FunPtr (Int4 -> IO ()) -> (Int -> IO ())

    type T5 = FunPtr (Int -> IO ()) -> (Int -> IO ())
    foreign import ccall "dynamic" mkFun5 :: T5

  Proposed change: none at present

section 5.5:

  It's going to be really hard to implement ForeignPtr as specified.
  The problem is that invocation of the cleanup function is triggered
  by the garbage collector.  I don't want the garbage collector to be
  recursively invoked so I don't want the garbage collector to
  directly invoke Haskell function.  The Hugs garbage collector is not
  supposed to be a mutator of the heap - so putting a simple wrapper
  round the garbage colector won't work.  And there's no mechanism
  outside the GC to look for cleanup functions to execute.

  GHC gets round this by scheduling a (preemptive) thread to execute
  the cleanup code.  How on earth does NHC get round this?  Does
  anyone have a suggestion for how it might be implemented in Hugs?

  Proposed change: none at present but I'm deeply sceptical of a
  design which takes a simple task (invoke a C cleanup function) and,
  for no discernable reason, generalizes it to the point that it 
  requires a much more complex runtime system.

section 5.6:

  castStablePtrToPtr and castPtrToStablePtr can break typesafety so
  one might want to try to make sure that any program that uses them
  will be forced to have the word 'unsafe' in them.

  Proposed change: none at present

Table 2 (section 6):

  Is there a reason to be so coy about the concrete C types used for
  HsChar, HsFloat, HsDouble and HsBool?

  Proposed change:

    C symbol    Haskell Symbol  Constraint on concrete C type
    HsChar      Char            unsigned char
    HsFloat     Float           float
    HsDouble    Double          double
    HsBool      Bool            int
  I see no reason at all not to specify HsBool.

  For HsChar, I'd like to know if it is signed or unsigned.
  I can imagine that the vague specification is to allow for wide
  characters but it's not clear to me that one could write much portable
  code without knowing that so it seems we should pick wide or narrow
  characters and stick with it.  (Hmmm, wonder how much code it would take
  to make Hugs work with wide characters?)

  For HsFloat/Double, I imagine we're being vague because Hugs
  implements Double with single precision floats and GHC on the Alpha
  (used to) implement Float with double precision floats.  I think
  Hugs can be fixed (in fact, was almost all done ages ago).  That
  leaves the question of whether we want to force Haskell implementations
  to follow C conventions.  I'm not sure.

Table 3 (section 6):

  Proposed change:

    Rename column 1 as 'Preprocessor symbol'.

    In the last 2 lines, change column 1 to read HS_BOOL_FALSE 
     and HS_BOOL_TRUE.  (This change merely standardizes the
     existing GHC fix for this problem.)

Alastair Reid        reid at cs.utah.edu        http://www.cs.utah.edu/~reid/

More information about the FFI mailing list