首页 文章

使用FFI时,C99 bool的等效Haskell类型是什么?

提问于
浏览
18

我有一个使用C99 bool 数据类型的库,我想通过FFI调用它 .

Haskell中C99 bool的对应类型是什么?在Foreign.C.types中有CInt,CShort等,但没有CBool .

如果 bool 没有"correct"类型,那么在期望 bool 的函数中传递的安全替代类型是什么?

另一种方法是修改C库,但我希望保持原样 .

5 回答

  • 12

    由于 sizeof(_Bool) 是在C99中实现定义的(参见ISO / IEC 9899:1999 6.2.5,6.2.6和6.5.3.4/4),明显的可移植解决方案是通过使用 int 而不是 bool 的包装来调用这些函数 . 或者,如果您不关心可移植性,可以查看编译器的文档以找出平台上的 sizeof(_Bool) ,并使用相应的FFI类型 .

    我猜测_983500_缺少 Foreign.C.Types 的原因是底层的C实现不会支持C99的所有功能 . 一个非常广泛使用的编译器(MSVC)根本不支持C99 .

  • 1

    据我所知,C99没有定义 _Bool 类型的确切大小( bool 映射到 _Bool ) . 你唯一知道的是它足够大以容纳值 01 . 因此,它的二进制表示依赖于编译器,这就是为什么,我想,它不存在于FFI支持库中 .

    以下程序是使用GCC 4.7.2编译的:

    #include <stdio.h>
    #include <stdbool.h>
    
    int main() {
        printf("%d", sizeof(bool));
        return 0;
    }
    

    给出以下输出:

    % gcc -std=c99 -o test test.c
    % ./test 
    1
    

    所以, bool 似乎映射到GCC中的 char . 您将看到的内容取决于您的编译器 .

    因此,我认为,如果你想要完全的可移植性,你最好为你的C函数编写一个包装器,它将采用普通的 int 并将其传递给带有类型转换的函数 .

  • 1

    bool 作为参数与 bool 结果类型之间存在差异 .


    我很确定,C99 bool是引入的(并且与所有其他基本值不同),因为前C99 BOOL不是一个足够好的 return 类型的函数:

    需要存在这样一个变量的内存表示,至少1个字节,但......

    • 汇编程序级别的布尔值的处理是通过依赖于FLAG的gotos完成的 . (见&&和||)

    • 应该可以使用更快的按位&和|而不是&&和||在布尔值,需要bool为1位 .

    • 函数的返回值应该能够使用FLAG寄存器(在某些机器上)而不是强制使用1位INT寄存器,甚至在INT寄存器中使用任何零/非零int .

    由于3.,恕我直言,除非我们在每个平台上考虑C99 bool使用的ABI(应用二进制接口),否则将不会有任何直接解决方案 . 修补haskell编译器以包装具有/应具有C99-bool结果类型的每个导入/导出的C函数可能更容易 .


    如果我没记错的话, int 是C函数 parameter 列表中大多数基本C类型的安全替代品 . 但是CChar很可能也会为bool做同样的事情(或更好) . 您可能想要了解 printf 使用的可变参数功能 ,...) .

  • 0

    如果您使用hsc2hs,则可以执行以下操作:

    #include <stdbool.h>
    
    type CBool = #{type bool}
    
    cFalse, cTrue :: CBool
    cFalse = 0
    cTrue = 1
    

    并且您还可以使用Foreign.Marshall.Utils中的 toBoolfromBool 函数在 CBoolBool 之间进行转换 .

    神奇的是在 #{type bool} 中,它告诉 hsc2hs 选择一个与C类型 bool 大小相同的Haskell数字类型 . 在我的机器上,结果是 Word8 .

  • 2

    base 库的 Foreign.C.Types.CBool 版本 4.10.0.0 ,对应于 ghc-8.2 .

    https://hackage.haskell.org/package/base-4.10.1.0/docs/Foreign-C-Types.html#t:CBool

相关问题