我有一个使用C99 bool
数据类型的库,我想通过FFI调用它 .
Haskell中C99 bool的对应类型是什么?在Foreign.C.types中有CInt,CShort等,但没有CBool .
如果 bool
没有"correct"类型,那么在期望 bool
的函数中传递的安全替代类型是什么?
另一种方法是修改C库,但我希望保持原样 .
我有一个使用C99 bool
数据类型的库,我想通过FFI调用它 .
Haskell中C99 bool的对应类型是什么?在Foreign.C.types中有CInt,CShort等,但没有CBool .
如果 bool
没有"correct"类型,那么在期望 bool
的函数中传递的安全替代类型是什么?
另一种方法是修改C库,但我希望保持原样 .
5 回答
由于
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 .据我所知,C99没有定义
_Bool
类型的确切大小(bool
映射到_Bool
) . 你唯一知道的是它足够大以容纳值0
和1
. 因此,它的二进制表示依赖于编译器,这就是为什么,我想,它不存在于FFI支持库中 .以下程序是使用GCC 4.7.2编译的:
给出以下输出:
所以,
bool
似乎映射到GCC中的char
. 您将看到的内容取决于您的编译器 .因此,我认为,如果你想要完全的可移植性,你最好为你的C函数编写一个包装器,它将采用普通的
int
并将其传递给带有类型转换的函数 .将
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
使用的可变参数功能,...)
.如果您使用hsc2hs,则可以执行以下操作:
并且您还可以使用Foreign.Marshall.Utils中的
toBool
和fromBool
函数在CBool
和Bool
之间进行转换 .神奇的是在
#{type bool}
中,它告诉hsc2hs
选择一个与C类型bool
大小相同的Haskell数字类型 . 在我的机器上,结果是Word8
.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