我在看 haskell-mpi binding ,我们有例如此签名在 mpi.h
:
int MPI_Initialized (int *flag);
其中
Internal.chs
表示如下:{#fun unsafe Initialized as ^ {alloca- `Bool' peekBool*} -> `()' discard*- #}
问:我无法理解输入参数周围发生的情况:
-
修饰符在做什么? c2hs wiki 说“Hs 函数的参数类型由所有编码规范的集合决定,其中 in 编码器后面没有减号”,但我仍然不明白。 int
的指针;输出编码器在做什么? AFAICT,它取消引用指针并将结果转换为 bool 值。它是否正确? 注意:
MPI_
前缀由 {# context prefix="MPI"#}
在函数名中引入.NB2:
peekBool :: (Storable a, Num a, Eq a) => Ptr a -> IO Bool
peekBool = liftM toBool . peek
NB3:
discard _ = return ()
,以及 *-
修饰符用于运行一元 Action 但丢弃其结果
最佳答案
我发现了解 C2HS 功能的最简单方法是查看它生成的 Haskell 代码。在这种情况下,函数 Hook
{#fun unsafe Initialized as ^ {alloca- `Bool' peekBool*} -> `()' discard*- #}
产生以下 Haskell 代码(稍微整理一下):
initialized :: IO Bool
initialized =
alloca $ \a ->
initialized'_ a >>= \res ->
discard res >>
peekBool a
foreign import ccall unsafe "Control/Parallel/MPI/Internal.chs.h MPI_Initialized"
initialized'_ :: Ptr CInt -> IO CInt
在这里,函数钩子(Hook)中输入参数的编码器后面的“
-
”意味着该参数实际上并不作为生成的 Haskell 函数的参数出现——在这种情况下,会发生一些空间分配给MPI_Initialized
的参数(使用 alloca
),使用指向该分配空间的指针调用 C 函数,并使用 peekBool
返回 Haskell 函数的输出从分配的空间中提取一个值。C2HS 产生的 Haskell 函数的类型只是
IO Bool
,即“输入”参数不会出现在任何地方。 (C2HS 文档确实这么说,但是在您看到示例之前很难解释它的含义!)输出编码器只是丢弃调用
MPI_Initialized
的结果。 C 函数,这是一个在这种情况下不是很有趣的状态代码。 C2HS 生成的 Haskell 代码的实际返回结果是由输出编码器为指向 MPI_Initialized
的指针参数生成的。功能。 peekBool
函数从 C 中读取一个整数值 int *
指针并将其转换为 Haskell Bool
;输出编码器中的“*
”表示该值应在 IO
中返回。单子(monad)。这种以“
-
”作为输入编码器的分配模式,以“IO *
”作为输出编码器的某种“窥视”函数(并且通常也忽略 C 函数的返回值)是很常见的。许多 C 库使用这种通过指针分配结果的模式,并且在 Haskell 中手动跟踪指针分配很烦人,因此 C2HS 试图帮助您管理它。需要一段时间才能习惯将所有“-
”和“*
”放在哪里,但是查看 C2HS 生成的 Haskell 代码是了解正在发生的事情的一个非常好的方法。
关于haskell - c2hs 输入输出类型编码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29654825/