How to pass arguments to foreign export functions into a Pipe?

166 views Asked by At

I have a

foreign export stdcall tick :: Integer -> Float -> Float -> IO Int

On each invocation of this function, I wish to pass its arguments into a set of pipes from the haskell pipes library.

Between the invocations I don't want the pipes to forget the minimum and maximum of the arguments of the last 10 invocations.

How should I do this?

1

There are 1 answers

1
Gabriella Gonzalez On

This is one of many things that pipes-concurrency is designed to do. What you do is spawn a buffer and every time you call the derived tick function it will stuff its arguments inside that buffer. Then you can have a pipe stream everything that comes out of that buffer.

import Control.Concurrent.Async
import Pipes
import Pipes.Concurrent
import qualified Pipes.Prelude as P

-- Your FFI tick function, which we will wrap with a derived function
ffi_tick :: Integer -> Float -> Float -> IO Int
ffi_tick _ _ _ = return 0

-- A data structure just to simplify the types
-- In theory I could have just used a tuple
data Ticker = Ticker
    { _tick  :: Integer -> Float -> Float -> IO Int
    , _input :: Input (Integer, Float, Float)
    }

-- This is in charge of buffer initialization and deriving the new
-- tick function
makeTicker :: IO Ticker
makeTicker = do
    (output, input) <- spawn Unbounded
    let tick x y z = do
            atomically $ send output (x, y, z)
            ffi_tick x y z
    return (Ticker tick input)

-- This is example code showing how you would use it    
main = do
    Ticker tick input <- makeTicker
    a <- async $ runEffect $ fromInput input >-> P.print
    tick 1 2.0 3.0
    tick 4 5.0 6.0
    tick 7 8.0 9.0
    wait a