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从OCaml调用haskell代码

下一篇: FFI和指针