How to access hs_free_fun_ptr from a Visual Studio DLL
Brian Hulley
brianh at metamilk.com
Sun Mar 26 17:56:00 EST 2006
Sven Panne wrote:
> Am Samstag, 25. März 2006 20:00 schrieb Brian Hulley:
>> I've found a workaround to the problem below: instead of trying to
>> use hs_free_fun_ptr, I instead pass a FunPtr to the Haskell function
>> freeHaskellFunPtr into my DLL, and use this to free everything,
>> finally using it to free itself (!) which I assume should be safe.
>> [...]
>
> It has been quite some time since I've worked on GHC's Adjustor.c and
> Hugs'
> FFI, but IIRC it is in general *not* safe to do this. On some
> platforms code
> is being generated dynamically for these kind of callbacks, which has
> already
> been freed by the time the callback returns. This might appear to
> work,
> depending on your processor architecture and dynamic memory management
> behaviour, but it's better not to rely on this. Perhaps the FFI spec
> should
> be clearer here.
>
> I had a similar problem in for timer callbacks in my GLUT binding.
> They are
> one-shot and have to clean themselves up after the callback executes.
> The
> solution was to register the FunPtrs to be cleaned up only and do the
> real
> work in another "scavenger" callback, see
> http://darcs.haskell.org/packages/GLUT/Graphics/UI/GLUT/Callbacks/Registration.hs
Thanks Sven for saving me from a horrible bug! :-) I've changed my code so
that the DLL now only uses the FunPtr to freeHaskellFunPtr to release other
callbacks, then I use freeHaskellFunPtr to free the FunPtr I passed in to
the DLL from the Haskell side of the API to avoid a closure freeing itself
ie:
foreign import ccall duma_begin :: FunPtr (FunPtr a -> IO ()) -> IO Bool
foreign import ccall duma_run :: IO ()
foreign import ccall duma_end :: IO ()
foreign import ccall "wrapper" mkFreeFunPtr :: (FunPtr a -> IO ()) -> IO
(FunPtr (FunPtr a -> IO ()))
run :: IO a -> IO ()
run f = bracket
(mkFreeFunPtr freeHaskellFunPtr
)
(\freeFunPtrFn -> do
duma_end
freeHaskellFunPtr freeFunPtrFn
)
(\freeFunPtrFn -> do
initialized <- duma_begin freeFunPtrFn
if (initialized)
then f >> duma_run
else return ()
)
Thanks, Brian.
More information about the Glasgow-haskell-users
mailing list