c2hs 输入和输出类型编组
c2hs in- and out- type marshalling
我正在查看 haskell-mpi binding,我们有例如mpi.h
中的签名:
int MPI_Initialized (int *flag);
其中在Internal.chs
中表示如下:
{#fun unsafe Initialized as ^ {alloca- `Bool' peekBool*} -> `()' discard*- #}
问:我无法理解输入参数周围发生的事情:
-
修饰符在做什么? c2hs wiki 说 "the argument type of the Hs function is determined by the set of all marshalling specifications where the in marshaller is not followed by a minus sign",但我还是不明白。
C函数接受一个指向int
的指针;输出编组器在做什么? AFAICT,它取消引用指针并将结果转换为布尔值。这是正确的吗?
注意:MPI_
前缀由 {# context prefix="MPI"#}
.
在函数名称中引入
NB2:
peekBool :: (Storable a, Num a, Eq a) => Ptr a -> IO Bool
peekBool = liftM toBool . peek
NB3:discard _ = return ()
,并且 *-
修饰符用于 运行 单子操作但丢弃其结果
我发现了解 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
这里,函数挂钩中输入参数的编组器后面的“-
”意味着该参数实际上并未作为结果 Haskell 函数的参数出现——在在这种情况下,会发生一些 space 被分配给 MPI_Initialized
的参数(使用 alloca
),使用指向分配的 space 的指针调用 C 函数,并且Haskell 函数的输出是 returned 使用 peekBool
从分配的 space.
中提取值
C2HS产生的Haskell函数的类型只是IO Bool
,即"input"参数没有出现在任何地方。 (C2HS 文档确实有点这样说,但在您看到示例之前很难解释它的含义!)
输出编组器只是丢弃调用 MPI_Initialized
C 函数的结果,这是一个在这种情况下不是很有趣的状态代码。 C2HS 生成的 Haskell 代码的 real return 结果是由 MPI_Initialized
函数的指针参数的输出编组器生成的。 peekBool
函数从 C int *
指针中读取一个整数值并将其转换为 Haskell Bool
;输出编组器中的“*
”意味着这个值应该在 IO
monad 中被 returned。
这种分配模式以“-
”作为输入编组器,某种 "peek" 函数以 "IO *
" 作为输出编组器(并且经常丢弃 C 函数的 return 值也是如此)很常见。许多 C 库使用这种通过指针分配结果的模式,并且在 Haskell 中手动跟踪指针分配很烦人,因此 C2HS 试图帮助您管理它。需要一段时间才能习惯将所有“-
"s and "*
”放在哪里,但是查看 C2HS 生成的 Haskell 代码是一个非常好的方法了解发生了什么。
我正在查看 haskell-mpi binding,我们有例如mpi.h
中的签名:
int MPI_Initialized (int *flag);
其中在Internal.chs
中表示如下:
{#fun unsafe Initialized as ^ {alloca- `Bool' peekBool*} -> `()' discard*- #}
问:我无法理解输入参数周围发生的事情:
-
修饰符在做什么? c2hs wiki 说 "the argument type of the Hs function is determined by the set of all marshalling specifications where the in marshaller is not followed by a minus sign",但我还是不明白。C函数接受一个指向
int
的指针;输出编组器在做什么? AFAICT,它取消引用指针并将结果转换为布尔值。这是正确的吗?
注意:MPI_
前缀由 {# context prefix="MPI"#}
.
NB2:
peekBool :: (Storable a, Num a, Eq a) => Ptr a -> IO Bool
peekBool = liftM toBool . peek
NB3:discard _ = return ()
,并且 *-
修饰符用于 运行 单子操作但丢弃其结果
我发现了解 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
这里,函数挂钩中输入参数的编组器后面的“-
”意味着该参数实际上并未作为结果 Haskell 函数的参数出现——在在这种情况下,会发生一些 space 被分配给 MPI_Initialized
的参数(使用 alloca
),使用指向分配的 space 的指针调用 C 函数,并且Haskell 函数的输出是 returned 使用 peekBool
从分配的 space.
C2HS产生的Haskell函数的类型只是IO Bool
,即"input"参数没有出现在任何地方。 (C2HS 文档确实有点这样说,但在您看到示例之前很难解释它的含义!)
输出编组器只是丢弃调用 MPI_Initialized
C 函数的结果,这是一个在这种情况下不是很有趣的状态代码。 C2HS 生成的 Haskell 代码的 real return 结果是由 MPI_Initialized
函数的指针参数的输出编组器生成的。 peekBool
函数从 C int *
指针中读取一个整数值并将其转换为 Haskell Bool
;输出编组器中的“*
”意味着这个值应该在 IO
monad 中被 returned。
这种分配模式以“-
”作为输入编组器,某种 "peek" 函数以 "IO *
" 作为输出编组器(并且经常丢弃 C 函数的 return 值也是如此)很常见。许多 C 库使用这种通过指针分配结果的模式,并且在 Haskell 中手动跟踪指针分配很烦人,因此 C2HS 试图帮助您管理它。需要一段时间才能习惯将所有“-
"s and "*
”放在哪里,但是查看 C2HS 生成的 Haskell 代码是一个非常好的方法了解发生了什么。