Haskell FFI:顶级 FunPtr 到顶级函数?

Fun*_*lad 3 haskell ffi

似乎最好只为顶级函数创建一次 FunPtr,而不是在需要时创建一个新函数(针对同一函数)并处理其释放。

我是否忽略了除 FunPtr 之外的其他获取 FunPtr 的方法foreign import ccall "wrapper"?如果没有,我的解决方法将如下面的代码所示。这样安全吗?

type SomeCallback = CInt -> IO ()

foreign import ccall "wrapper" mkSomeCallback :: SomeCallback -> IO (FunPtr SomeCallback)

f :: SomeCallback
f i = putStrLn ("It is: "++show i)

{-# NOINLINE f_FunPtr #-}
f_FunPtr :: FunPtr SomeCallback
f_FunPtr = unsafePerformIO (mkSomeCallback f)
Run Code Online (Sandbox Code Playgroud)

编辑:已验证“每次都创建一个新的”变体(main = forever (mkSomeCallback f))实际上会泄漏内存(如果不freeHaskellFunPtr这样做的话)。

bdo*_*lan 5

原则上,这应该是安全的 - GHC 内部代码使用类似的模式来初始化单例,例如 IO 监视句柄队列。请记住,您无法控制 mkSomeCallback 何时运行,并且不要忘记NOINLINE.