Search code examples
haskellc2hs

how to declare a callback to Haskell land


I am interfacing to a C library, and there's a function that has a callback argument of type (int (*fun) (void *)).

How would I handle this with c2hs? I don't see callbacks mentioned in https://github.com/haskell/c2hs/wiki/Implementation-of-Haskell-Binding-Modules or http://www.cse.unsw.edu.au/~chak/papers/Cha99b.html .

In my actual application, the callback does not do any computation - it just needs to check whether some flag was set meanwhile, and I want to set it from a Haskell thread. (So the obvious work-around is to declare the callback, and the flag, in C land, and have a Haskell function just set the flag.)

(Edit) I also checked https://wiki.haskell.org/Calling_Haskell_from_C but rejected it because of "ghc -c ... will create Safe_stub.c ..." and I was sure that compilation to C was long gone. But indeed I get a stub.h (do I need it?) and the object file.


Solution

  • I don't know whether c2hs has any special support for this, but it sounds like what you want is a 'foreign import "wrapper"'. See under "Dynamic wrapper" in the Haskell 2010 report here.

    Specifically, if you have

    foreign import ccall "c_name" c_function_that_takes_a_callback ::
        FunPtr (Ptr Foo -> IO Int) -> IO () -- or whatever the whole type is
    

    then you want

    foreign import ccall "wrapper" makeFooWrapper ::
        (Ptr Foo -> IO Int) -> IO (FunPtr (PtrFoo -> IO Int))
    

    Then you can implement your callback in Haskell as a function Ptr Foo -> IO Int, pass that to makeFooWrapper and then pass the result to c_function_that_takes_a_callback.