Haskell FFI - can you obtain a C Pointer from a Ha

2019-03-22 04:36发布

问题:

I have quite a few C structs structured like

typedef struct {
    unsigned int a;
    unsigned int b;
} StructA;

And a lot of functions like

void doSomethingWith(StructA*,StructB*,StructC*);

Is there an easy way to call these functions with Haskell FFI? Like, is there something that behaves like the & operator in C? (I imagine there isn't, but if there was I'd like to know). Do I have to make the Haskell side data's instance of storeable (I don't have any constructor functions for these structs).

Also: If I have to pass a struct instead of a struct pointer (not a hypothetical question, I have a few functions like that - it's not my code so I can't do anything about it), can I just pass the components of the struct instead? Like if I want to call

void function(StructA);

can I do this with

foreign import ccall "function" :: CUInt -> CUInt -> IO()

?

回答1:

To pass a reference to Haskell data to C, where the memory is allocated in the Haskell heap, and C will operate on the data directly, you need to:

  • ensure it has the correct shape in memory (via a Storable instance that maps A to the an identical byte structure as StructA).
  • allocate and fill pinned memory on the Haskell heap, via mallocForeignPtr

There are several consequences to consider in this approach:

  • GHC will de-allocate the value once you drop all references to the ForeignPtr -- so you will need to be sure that the C side won't touch it again
  • You're letting C mess with stuff on the Haskell heap, so make sure its correct

Other options:

  • pass opaque references to C via a StablePtr
  • allocate and memory on the C side, and use a finalizer to free it.


标签: c haskell ffi