Hello, I'm working on interfacing a c library that has the notion of callbacks. I have a C function: f_setCallback( void (funptr*) () ); I would like to allow a haskell developer to have an interface like the following: callback :: IO () callback = putStr "Called!\n" main :: IO () main = do setCallback callback -- etc. Is this possible via. ffi? If so, how would I do it code wise? Thanks, David J. Sankel
Hello,
I'm working on interfacing a c library that has the notion of callbacks.
I have a C function:
f_setCallback( void (funptr*) () );
I would like to allow a haskell developer to have an interface like the following:
callback :: IO () callback = putStr "Called!\n"
main :: IO () main = do setCallback callback -- etc.
Is this possible via. ffi? If so, how would I do it code wise?
foreign import ccall "wrapper" mkCallback :: IO () -> FunPtr (IO ()) foreign import ccall "f_setCallback" f_setCallback :: FunPtr (IO ()) -> IO () setCallback cb = mkCallback cb >>= f_setCallback That solution has one slight disadvantage, though: mkCallback dynamically creates an "adjustor thunk", which is a short piece of machine code that translates from the C calling convention to Haskell. This thunk should be freed using freeHaskellFunPtr when it is no longer needed (i.e. when a different callback is installed). So setCallback should really check if there is already a _Haskell_ callback installed, and if so, free it using freeHaskellFunPtr. Otherwise, you'd have a small memory leak. Cheers, Wolfgang
On 02-Mar-2003, Wolfgang Thaller <wolfgang.thaller@gmx.net> wrote:
I have a C function:
f_setCallback( void (funptr*) () );
That is a very bad design. You should change the interface of your C function to f_setCallback( void (funptr*) (void *), void * ); -- Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp.
--- Wolfgang Thaller <wolfgang.thaller@gmx.net> wrote:
foreign import ccall "wrapper" mkCallback :: IO () -> FunPtr (IO ()) foreign import ccall "f_setCallback" f_setCallback :: FunPtr (IO ()) -> IO ()
setCallback cb = mkCallback cb >>= f_setCallback
Thanks for the help. Is there a ghc bug with wrappers like this? Compiling that code gives me: Unacceptable result type in foreign declaration: FunPtr (IO ()) When checking declaration: foreign import ccall safe "wrapper" mkCallback :: IO () -> FunPtr (IO ()) Thanks, David J. Sankel
David Sankel wrote:
--- Wolfgang Thaller <wolfgang.thaller@gmx.net> wrote:
foreign import ccall "wrapper" mkCallback :: IO () -> FunPtr (IO ())
Answering my own question, this should be:
foreign import ccall "wrapper" mkCallback :: IO () -> IO( FunPtr (IO ()) )
Of course. Sorry for posting without thinking... :-/ Cheers, Wolfgang
participants (3)
-
David Sankel -
Fergus Henderson -
Wolfgang Thaller