FFI Haskell Callback with State - haskell

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.

Related

Generate stateful function pointer for FFI testing

I want to generate stateful functions (C signature T f()) with QuickCheck as arguments for foreign functions. Preferably I also want to make them (or their inner s->(T,s)) showable.
I know that for stateless functions I can write something like
type Compare = CInt -> CInt -> CBool
foreign import ccall "wrapper"
mkCompare :: Compare -> IO (FunPtr Compare)
but I got stuck trying this approach for the stateful functions, as I don't see how I can translate the monad hiding the state in Haskell to the function hiding the state in C.
Example of a stateful function f
static int i = 0;
int f() {
return i++;
}
In Haskell I would represent this function as State (\s -> (s,s+1)).
What does QuickCheck have to do with it?
If I have a C function that takes a stateful function as argument, e.g.
int twice(int (*f)()) {
f();
return f();
}
then I can test the function with QuickCheck, where QuickCheck can generate different implementations for f, which would usually look similar to
prop_total (Fun f) xs = total $ g f xs
but these generated functions are stateless, not stateful like the example C function above.
Thanks to Daniel Wagner's suggestion in the comments, I could figure it out. The Show instance comes for free. Here's a minimal example that I ran with
gcc -fPIC -shared -o libstateful.dylib stateful.c && ghc -L. Stateful.hs -lstateful && ./Stateful
As expected it will output a distribution of about 50% of 1 (True) and 50% of 0 (False).
Stateful.hs
import Data.IORef
import Foreign.C
import Foreign.Ptr
import System.IO.Unsafe
import Test.QuickCheck
instance CoArbitrary CInt where
coarbitrary = coarbitraryIntegral
instance Arbitrary CBool where
arbitrary = chooseEnum (0,1)
shrink 1 = [0]
shrink 0 = []
instance Function CInt where
function = functionIntegral
type Generator = IO CBool
foreign import ccall "wrapper" mkGenerator :: Generator -> IO (FunPtr Generator)
foreign import ccall "changes" changes :: FunPtr Generator -> IO CBool
type StateFn = CInt -> (CBool,CInt)
stateFnToIORef :: StateFn -> IORef CInt -> IO CBool
stateFnToIORef f s_ref = do
s <- readIORef s_ref
let (a,s') = f s
writeIORef s_ref s'
pure a
prop_changes :: Fun CInt (CBool,CInt) -> Property
prop_changes (Fn f) = unsafePerformIO (do
x_ref <- newIORef 0
f' <- mkGenerator $ stateFnToIORef f x_ref
res <- changes f'
pure $ collect res (total res))
main :: IO ()
main = quickCheck prop_changes
stateful.c
_Bool changes(_Bool (*f)()) {
_Bool x = f();
_Bool y = f();
return x != y;
}

How do I pass Haskell data through a C FFI as an opaque data type?

I'm trying to pass some data through a C library that doesn't read or modify that data.
foreign import ccall "lua.h lua_pushlightuserdata"
c_lua_pushlightuserdata :: LuaState -> Ptr a -> IO ()
foreign import ccall "lua.h lua_touserdata"
c_lua_touserdata :: LuaState -> CInt -> IO (Ptr a)
data MyData =
MyData
{ dataIds = TVar [Int]
, dataSomethingElse = [String]
}
calledFromRunLuaState :: LuaState -> IO ()
calledFromRunLuaState luaState = do
dataPtr <- c_lua_touserdata luaState (-1)
myData <- dataFromPtr dataPtr
doSomethingWith myData
main = do
luaState <- Lua.newstate
ids <- atomically $ newTVar []
c_lua_pushlightuserdata luaState (dataToPtr (MyData ids []))
runLuaState luaState
I'm trying to figure out how to define dataFromPtr and dataToPtr.
This is what StablePtr is for. So you have to use newStablePtr in place of your dataFromPtr and deRefStablePtr in place of your dataToPtr. Note that deRefStablePtr operates in the IO monad, so you would have to ajust your code accordingly. Also, you would have to adjust the foreign imports to use stable pointers, e.g.:
foreign import ccall "lua.h lua_pushlightuserdata"
c_lua_pushlightuserdata :: LuaState -> StablePtr MyData -> IO ()
and similarly for lua_touserdata.
Finally, when you create a stable pointer with newStablePtr, the garbage collector will not deallocate that value automatically. So it is your responsibility to deallocate it by calling freeStablePtr.

C2HS marshalling double pointer

When there is a function like:
some_type_t* some_type_create(const char* name, char** errptr);
is there a way to get C2HS to generate a Haskell binding with the following signature?
someTypeCreate :: String -> IO (SomeTypeFPtr, String)
Here is what I can get so far:
{#fun some_type_create as ^
{`String', alloca- `Ptr CChar' peek*} -> `SomeTypeFPtr' #}
and it works in a way that I get
someTypeCreate :: String -> IO (SomeTypeFPtr, (Ptr CChar))
but how do I make it return IO (SomeTypeFPtr, String)
(or better IO (Either String SomeTypeFPtr)) since String represents the error)?
I assume that I should use/write a different marshaller to use instead of peek which would convert the result type but I don't quite understand how to do it.
I think I've figured it out, I just wrote the following marshallers:
nullableM :: (Ptr a -> IO b) -> Ptr a -> IO (Maybe b)
nullableM f ptr = if ptr == nullPtr
then return Nothing
else liftM Just $ f ptr
{-# INLINE nullableM #-}
toStringMaybe :: CString -> IO (Maybe String)
toStringMaybe = nullableM peekCString
{-# INLINE toStringMaybe #-}
peekStringMaybe :: Ptr CString -> IO (Maybe String)
peekStringMaybe x = peek x >>= toStringMaybe
{-# INLINE peekStringMaybe #-}

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

Resources