haskell - c2hs 输入输出类型编码

标签 haskell ffi c2hs

我在看 haskell-mpi binding ,我们有例如此签名在 mpi.h :

int MPI_Initialized (int *flag); 

其中Internal.chs表示如下:
{#fun unsafe Initialized as ^ {alloca- `Bool' peekBool*} -> `()' discard*- #}

问:我无法理解输入参数周围发生的情况:
  • 什么是-修饰符在做什么? c2hs wiki 说“Hs 函数的参数类型由所有编码规范的集合决定,其中 in 编码器后面没有减号”,但我仍然不明白。
  • C 函数采用指向 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/

    相关文章:

    haskell - 使用 c2hs 和 cabal 构建

    haskell - c2hs - 匿名枚举?

    parsing - Attoparsec 在大型 'take' 调用上分配大量内存

    Haskell 管道过滤不同值

    pointers - 将 Option<&mut T> 转换为 *mut T

    rust - 我如何在 Rust 代码中表示 C 的 "unsigned negative"值?

    haskell - 如何使用 Haskell 的 graphviz 包绘制图形标签

    haskell - 如何查看解析后的Aeson Value?

    rust - 如何使用 Rust 中的 C typedef 结构和该结构的函数?