Exporting/importing via FFI vs. using the FFI wrapper - haskell

I inherited a code base using the following idiom, which exports and then reimports a function via the FFI:
foreign export ccall someHaskellFn :: a -> IO b
foreign import ccall "&someHaskellFn"
someHaskellFn_addr :: FunPtr (a -> IO b)
Neither the Haskell function someHaskellFn, nor the exported function is ever used; only someHaskellFn_addr is required, and is always used in an IO context:
-- frob :: FunPtr (a -> IO b) -> IO ()
frob someHaskellFn_addr
I'm wondering whether this has any advantages over using a wrapper function:
foreign import ccall "wrapper"
mkWrapper :: (a -> IO b) -> IO (FunPtr (a -> IO b))
-- Function pointer to someHaskellFn, never freed
someHaskellFnPtr = mkWrapper someHaskellFn
frob =<< someHaskellFnPtr
The documentation for Foreign.Ptr mentions these two methods to create a value of type FunPtr a:
A value of type FunPtr a may be a pointer to a foreign function,
either returned by another foreign function or imported with a a
static address import like
foreign import ccall "stdlib.h &free"
p_free :: FunPtr (Ptr a -> IO ())
or a pointer to a Haskell function created using a wrapper stub
declared to produce a FunPtr of the correct type.
It also says
Calls to wrapper stubs […] allocate storage, which should be released with freeHaskellFunPtr when no longer required.
My understanding is that the wrapper using code behaves indentical (on the Haskell side) to the export/import variant; is this correct? Are there any finer details about foreign function imports and exports which I am missing?

Related

Error when trying to use a ForeignPtr argument to a dynamic wrapper

I'm trying to wrap a C library using c2hs. I've got an opaque C struct that I've mapped in Haskell as follows:
{#pointer *foo as Foo foreign newtype #}
I've used a foreign pointer so I can automatically clean up with a finalizer. All of that seems to work fine. However, I now want to wrap a function pointer that looks like the following:
typedef void (*hook_func)(foo *f, int a);
My Haskell code then looks like this:
type HookFunc = Foo -> Int -> IO ()
foreign import ccall "wrapper"
mkHookFunc :: HookFunc -> IO (FunPtr HookFunc)
However, when I compile I get the following error:
Unacceptable argument type in foreign declaration:
ForeignPtr Foo
Any ideas on the best solution to this error? My initial thinking is that I need to use unsafeForeignPtrToPtr to convert to just a foo pointer, but I'm not sure how to do this/where to put it in the "wrapper".
Any clues?
I think I sorted it out.
I ended up finding some code in gtk2hs that did something similar to what I wanted (https://github.com/gtk2hs/gtk2hs/blob/master/gio/System/GIO/Async/AsyncResult.chs)
I defined my callback as normal:
type HookFunc = Foo -> Int -> IO ()
Then I also defined another type that used types from Foreign.C, i.e.
type CHookFunc = Foo -> CInt -> IO ()
The wrapper then looked like:
foreign import "wrapper"
mkHookFunc :: CHookFunc -> IO {# type hook_func_t #} -- hook_func_t is the typedef in the C header file
Finally, I added a marshalling function as follows:
marshalHookFunc :: HookFunc -> IO {# type hook_func_t #}
marshalHookFunc hookFunc =
mkHookFunc $ \fooPtr i -> do
foo <- mkFoo fooPtr -- mkFoo constructs a ForeignPtr Foo out of a Ptr Foo
hookFunc foo i

Haskell - 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

Calling a C function that is referenced by a C pointer to that function with Haskell FFI

There is a functions in the 'C' wiringPi library with type,
extern void (*pinMode) (int pin, int mode) ;
I tried calling it from haskell using the FFI with FunPtr. So I did,
foreign import ccall unsafe "wiringPi.h &pinMode" c_pinMode
:: FunPtr (CInt -> CInt -> IO ())
foreign import ccall "dynamic" dc_pinMode
:: FunPtr (CInt -> CInt -> IO ()) -> (CInt -> CInt -> IO ())
but for some reason, even though it compiles, it doesn't seem to be calling the function that 'pinMode' points to.
So I tried using normal Foreign.Ptr, thinking I might be able to peek at the Ptr to get a reference to the underlying 'C' function pointed to by 'pinMode'. So I tried,
foreign import ccall "wiringPi.h &pinMode" c_pinMode
:: Ptr (Ptr (CInt -> CInt -> IO ()))
And then, in the implementation of the haskell function that calls 'pinMode' I used peek twice to get a reference to the underlying function. But I keep getting compilation errors where the compiler tell me that the function of type (CInt -> CInt -> IO ()) is not an instance of the 'Storable' typeclass.
So I checked out the storable typeclass, to make (CInt -> CInt -> IO ()) an instance of the storable typeclass.. The minimum implementation required is for peek, poke and a few other functions.. I realized, it really shouldn't be so difficult to call a function that is reference by a pointer..
I feel like I am missing something fundamental. Can someone please point me in the right direction?
Thanks and Regards
Suppose we have a C function pointer defined in foo.c.
void foo(int x, int y)
{
printf("foo: sum = %d\n", x+y);
}
typedef void (*FooPtr) (int, int);
FooPtr fooptr = foo;
In order to call the function that fooptr points to, we need to not only declare a static address import, but also a dynamic import. The dynamic stub can help us convert FunPtr values to corresponding Haskell functions.
type Foo = CInt -> CInt -> IO ()
foreign import ccall "foo.c &fooptr" fooptr :: Ptr (FunPtr Foo)
foreign import ccall "dynamic" mkFooFun :: FunPtr Foo -> Foo
main = do
funcptr <- peek fooptr
mkFooFun funcptr 1 2
fooptr is an imported address that points to a foreign function. Its type is neither Ptr (Ptr a) nor FunPtr a.
If we import foo's address, its type will be FunPtr Foo. In order to use it, we still need the help from mkFooFun.
foreign import ccall "foo.c &foo" fooptr2 :: FunPtr Foo
main = mkFooFun fooptr2 1 2
In this example, since we can access foo, the simplest way to call foo is
foreign import ccall "foo.c foo" foo :: Foo
main = foo 1 2

FFI Haskell Callback with State

My question is about how to write friendly Haskell Interfaces that model callbacks which can be invoked from C code. Callbacks are addressed here (HaskellWiki), however, I believe this question is more complex than the example from that link.
Suppose we have C code, requiring callbacks and the header looks like the following:
typedef int CallbackType(char* input, char* output, int outputMaxSize, void* userData)
int execution(CallbackType* caller);
In this case the function execution takes a callback function and will use that to process new data, essentially a closure. The call back expects an input string, an output buffer which has been allocated with size outputMaxSize and the userData pointer, which can be casted however inside the callback.
We do similar things in haskell, when we pass around closures with MVars, so we can still communicate. Therefore when we write the Foreign interface, we'd like to keep this sort of type.
Specifically here is what the FFI Code might look like:
type Callback = CString -> CString -> CInt -> Ptr () -> IO CInt
foreign import ccall safe "wrapper"
wrap_callBack :: Callback -> IO (FunPtr Callback)
foreign import ccall safe "execution"
execute :: FunPtr Callback -> IO CInt
Users should be able to do this sort of thing, but it feels like a poor interface since
they need to write callbacks with type Ptr (). Rather we'd like to replace this with MVars
which feel more natural. So we'd like to write a function:
myCallback :: String -> Int -> MVar a -> (Int, String)
myCallback input maxOutLength data = ...
In order to convert to C, we'd like to have a function like:
castCallback :: ( String -> Int -> MVar a -> (Int, String) )
-> ( CString -> CString -> CInt -> Ptr () -> IO CInt )
main = wrap_callBack (castCallback myCallback) >>= execute
In this case castCallback is for the most part not hard to implement,
convert string -> cstring, Int -> CInt, and copy over the output string.
The hard part however is resolving the MVar to Ptr, which is not necessarily storable.
My Question is what is the best way to go about writing callback code in Haskell, which can still be communicated with.
If you want to access a Haskell structure like MVar which doesn't have a library function to convert it to a pointer representation (meaning it is not supposed to be passed to C), then you need to do partial function application.
In the partial function application, the trick is to build a partial function with MVar already applied, and pass the pointer to that function to C. C will then call it back with the object to put in MVar. An example code below (all the code below is derived from something I did before - I modified it for examples here but haven't tested the modifications):
-- this is the function that C will call back
syncWithC :: MVar CInt -> CInt -> IO ()
syncWithC m x = do
putMVar m x
return ()
foreign import ccall "wrapper"
syncWithCWrap :: (CInt -> IO ()) -> IO (FunPtr (CInt -> IO ()))
main = do
m <- newEmptyMVar
-- create a partial function with mvar m already applied. Pass to C. C will back with CInt
f <- syncWithCWrap $ syncWithC m
What if your MVar object is more complex? Then you need to build a Storable instance of the MVar object if it doesn't exist. For example, if I want to use an MVar with array of pair of Ints, then first define a Storable instance of Int pairs (SV is Storable Vector, MSV is Storable Mutable Vector):
data VCInt2 = IV2 {-# UNPACK #-} !CInt
{-# UNPACK #-} !CInt
instance SV.Storable VCInt2 where
sizeOf _ = sizeOf (undefined :: CInt) * 2
alignment _ = alignment (undefined :: CInt)
peek p = do
a <- peekElemOff q 0
b <- peekElemOff q 1
return (IV2 a b)
where q = castPtr p
{-# INLINE peek #-}
poke p (IV2 a b) = do
pokeElemOff q 0 a
pokeElemOff q 1 b
where q = castPtr p
{-# INLINE poke #-}
Now, you can just pass a pointer to the vector to C, have it update the vector, and call back the void function with no arguments (since C is already filling the vector). This also avoid expensive data marshalling by sharing memory between Haskell and C.
-- a "wrapper" import is a converter for converting a Haskell function to a foreign function pointer
foreign import ccall "wrapper"
syncWithCWrap :: IO () -> IO (FunPtr (IO ()))
-- call syncWithCWrap on syncWithC with both arguments applied
-- the result is a function with no arguments. Pass the function, and
-- pointer to x to C. Have C fill in x first, and then call back syncWithC
-- with no arguments
syncWithC :: MVar (SV.Vector VCInt2) -> MSV.IOVector VCInt2 -> IO ()
syncWithC m1 x = do
SV.unsafeFreeze x >>= putMVar m1
return ()
On C side, you will need a struct declaration for VCInt2 so that it knows how to parse it:
/** Haskell Storable Vector element with two int members **/
typedef struct vcint2{
int a;
int b;
} vcint2;
So, on C side, you are passing it vcint2 pointer for MVar object.

Haskell FFI: Top-level FunPtr to a top-level function?

It seems desirable to create a FunPtr to a top-level function just once instead of creating a new one (to the same function) whenever it's needed and dealing with its deallocation.
Am I overlooking some way to obtain the FunPtr other than foreign import ccall "wrapper"? If not, my workaround would be as in the code below. Is that safe?
type SomeCallback = CInt -> IO ()
foreign import ccall "wrapper" mkSomeCallback :: SomeCallback -> IO (FunPtr SomeCallback)
f :: SomeCallback
f i = putStrLn ("It is: "++show i)
{-# NOINLINE f_FunPtr #-}
f_FunPtr :: FunPtr SomeCallback
f_FunPtr = unsafePerformIO (mkSomeCallback f)
Edit: Verified that the "creating a new one every time" variant (main = forever (mkSomeCallback f)) does in fact leak memory if one doesn't freeHaskellFunPtr it.
This should, in principle, be safe - GHC internal code uses a similar pattern to initialize singletons such as the IO watched-handles queues. Just keep in mind that you have no control over when mkSomeCallback runs, and don't forget the NOINLINE.

Resources