我有一个使用C99 bool
数据类型的库,我想通过FFI调用它。
Haskell中C99 bool的对应类型是什么?在Foreign.C.types中有CInt,CShort等,但没有CBool。
如果bool
没有“正确”类型,那么在期望bool
的函数中传递的安全替代类型是什么?
另一种方法是修改C库,但我希望保持原样。
答案 0 :(得分:12)
由于sizeof(_Bool)
是在C99中实现定义的(参见ISO / IEC 9899:1999 6.2.5,6.2.6和6.5.3.4/4),明显的可移植解决方案是通过包装器调用这些函数使用int
代替bool
。或者,如果您不关心可移植性,可以查看编译器的文档以找出平台上的sizeof(_Bool)
并使用相应的FFI类型。
我猜测CBool
缺少Foreign.C.Types
的原因是底层C实现不会支持C99的所有功能。一个非常广泛使用的编译器(MSVC)根本不支持C99。
答案 1 :(得分:2)
据我所知,C99没有定义_Bool
类型的确切大小(bool
映射到_Bool
)。您唯一知道的是它足够大,可以容纳值0
和1
。因此,它的二进制表示依赖于编译器,这就是为什么,我想,它不存在于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
并将其传递给具有类型转换的函数。
答案 2 :(得分:1)
将bool
作为参数与bool
结果类型之间存在差异。
我很确定,C99 bool已经推出(并且与所有其他基本值不同),因为前C99 BOOL不够好返回类型的函数:< / p>
需要存在这样一个变量的内存表示,至少1个字节,但是......
汇编程序级别的布尔值处理是通过依赖FLAG的gotos完成的。 (见&amp;&amp;和||)
应该可以使用更快的按位&amp;和|而不是&amp;&amp;和||在布尔值上,需要bool为1位。
函数的返回值应该能够使用FLAG寄存器(在某些机器上) 而不是强迫使用1位INT寄存器,甚至在INT寄存器中使用任何零/非零int。
因为3.,恕我直言, 除非我们在每个平台上考虑C99 bool使用的ABI(应用程序二进制接口),否则将不会有任何直接解决方案。修补haskell编译器以包装每个具有/应该具有C99-bool结果类型的导入/导出的C函数可能更容易。
如果我没记错的话,int
是C函数参数列表中大多数基本C类型的安全替代品。但是CChar很可能也会为bool做同样的事情(或更好)。您可能想要了解,...)
使用的变量参数功能printf
。
答案 3 :(得分:1)
如果您使用hsc2hs,则可以执行此操作:
#include <stdbool.h>
type CBool = #{type bool}
cFalse, cTrue :: CBool
cFalse = 0
cTrue = 1
您还可以使用Foreign.Marshall.Utils中的toBool
和fromBool
功能在CBool
和Bool
之间进行转换。
魔法在#{type bool}
,告诉hsc2hs
选择Haskell数字类型,其大小与C类型bool
相同。在我的机器上,结果是Word8
。
答案 4 :(得分:0)
base
库的版本为Foreign.C.Types.CBool
4.10.0.0
ghc-8.2
,对应{{1}}。
https://hackage.haskell.org/package/base-4.10.1.0/docs/Foreign-C-Types.html#t:CBool