unsafePerformIO和FFI库初始化(unsafePerformIO and FFI li

2019-08-05 12:04发布

我创建C中的FFI模块的库,希望被称为1次,不可重入函数之前别的是。 这个调用是幂等的,但有状态,所以我只是把它在每一个哈斯克尔通话。 但是,它的速度慢,并且由于非重入可能会导致冲突。

因此,这是使用unsafePerformIO正确的时间? 我可以在一个不安全的IOREF或无功换一个布尔值,使通过忽略后续调用(调用在全球,隐藏IOREF状态是假)幂等这些初始化调用。

如果没有,什么是做的正确方法?

Answer 1:

我喜欢初始化一次,并提供伪造的令牌,你已经初始化的机器证据的方法。

所以,你的证据是:

data Token = Token

你出口抽象。

那么你的初始化函数可以返回这方面的证据。

init :: IO Token

现在,你需要的是证明传递到您的API:

bar  :: Token -> IO Int
bar !tok = c_call_bar

等等

现在你可以用这个东西了一个单子,或者一些更高阶的初始化环境,使之更清洁,但是这是基本的想法。

与初始化使用隐藏状态的C库的问题是,你最终要么不能够并行访问图书馆,或有问题GHCI,混合编译字节码,有两个不同的版本加载的C库(这将失败,链接错误)。



Answer 2:

我想指出,目前一些新的技巧,建议为/,而不是withSocketsDo 由尼尔·米切尔的基础上evaluate (“强制执行所产生的IO操作时它的参数进行评估,以微弱的头部正常形态。”):

withSocketsDo act = do evaluate withSocketsInit; act 

{-# NOINLINE withSocketsInit #-}
withSocketsInit = unsafePerformIO $ do
    initWinsock
    termWinsock

我以消除调用withSocketsDo要求的办法是使很便宜,然后到处洒它可能是必要的。

不一定,这是一个美好的理想......

(另见他的回答宣布在图书馆此更新。)



文章来源: unsafePerformIO and FFI library initialization