问题
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.
来源:https://stackoverflow.com/questions/10900354/haskell-ffi-can-you-obtain-a-c-pointer-from-a-haskell-data-structure