FFI and Pointers
I'm using the FFI in order to use a function in C that takes a struct and returns the same struct. The references I saw say I have to use pointers to these structures in order to be able to import it into Haskell. So, for example.
data Bar = Bar { a :: Int, b :: Int }
type BarPtr = Ptr (Bar)
foreign import ccall "static foo.h foo"
f_foo :: BarPtr -> BarPtr
Now I have the problem that I have to be able to use the function. The references I saw had functions of type BarPtr -> IO () and used with , which has signature Storable a => a -> (Ptr a -> IO b) -> IO b , which was ok, because they where calling the function inside main.
However, I would like to wrap this function in a library, getting a function of type Bar -> Bar without IO, is it possible to do without unsafePerformIO ? What's the procedure?
It's not possible to remove IO
from the type without using unsafePerformIO
. However, it is possible to get a function with the type you want in this case, with some caveats. Specifically the C function "foo" cannot depend upon any global variables, thread-local state, or anything besides the single argument. Also, calling foo(bar)
should always provide the same result when bar
is unchanged.
I expect that trying to import the C function
bar foo(bar input);
with this call
f_foo :: BarPtr -> BarPtr
will result in a compiler error due to the result type. I think you may need to write a wrapper function (in C):
void wrap_foo(bar *barPtr) {
bar outp = foo(*barPtr);
*barPtr = outp;
}
and import it as
f_wrap_foo :: BarPtr -> IO ()
Finally, you would call this imported function with:
fooBar :: Bar -> Bar
fooBar bar = unsafePerformIO $ with bar $ barPtr -> do
f_wrap_foo barPtr
peek barPtr
链接地址: http://www.djcxy.com/p/61184.html
下一篇: FFI和指针