FW: H/Direct

Simon Peyton-Jones simonpj at microsoft.com
Wed Dec 6 10:10:26 EST 2000


Here's a question from Koen that bears on the FFI.

Simon

-----Original Message-----
From: Koen Claessen [mailto:koen at cs.chalmers.se]
Sent: 04 December 2000 12:55
To: Erik Meijer; Simon Peyton-Jones; Sigbjorn Finne
Subject: H/Direct


Hi H/Direct team,

I have been using H/Direct for quite a while now, and I am a
happy user (apart from the massive amount of work involved
in getting the system to run for both Hugs and GHC -- there
seems to be a circular import which Hugs complains about and
which can be skillfully removed, but which GHC depends on or
something.)

I have a question about marshalling arguments which are
expensive to marshall in H/Direct. Often you want this
result to be shared between calls of the functions.

Currently, I have applied the following technique a couple
of times and I wonder if it can be made more general and
added to H/Direct.

For example, I have a BDD package with the following
operation (I have simplified this type a bit):

  [pure]Bdd *BddReplace
    ( [size_is(n),in] int *xs
    ,                 int n
    , [in]            Bdd *bdd
    );

(The argument "xs" encodes a variable mapping, which is used
to construct a new BDD from the argument.) I want this to be
a function in Haskell with the type:

  replace :: [Int] -> Bdd -> Bdd

The way I often use replace is by defining:

  prime :: Bdd -> Bdd
  prime = replace [ extremely-long-list ]

Here, I want the marshalling of the list to happen once, and
to be shared between calls to prime.

So I wrote my own version of replace in Haskell. Here it is:

  replace :: [Int] -> (Bdd -> Bdd)
  replace xs =
    unsafePerformIO $
      do array <- newCArray (length n)
         sequence [ setCArray array i x
                  | (i,x) <- [0..] `zip` xs
                  ]
         return (\bdd -> primBddReplace bdd array)

Note the brackets in the type to indicate I am returning a
function. Now, the CArray interface must look like this:

  [finaliser("free")]
  interface CArray {};

  CArray *newCArray( int n );
  void   setCArray( CArray *arr, int i, int n );
  int    readCArray( CArray *arr, int i );

This is because "replace" should not free the C-array until
it looses track of the returned function.

It works great! The question is: can this be done by
inventing some new annotation for the IDL code? One problem
is maybe that the sharing of these things can only be done
in a certain order.

Regards,
Koen.

--
Koen Claessen         http://www.cs.chalmers.se/~koen     
phone:+46-31-772 5424      mailto:koen at cs.chalmers.se
-----------------------------------------------------
Chalmers University of Technology, Gothenburg, Sweden




More information about the FFI mailing list