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

时间:2013-03-12 17:59:11

标签: haskell c99 ffi

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

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

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

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

5 个答案:

答案 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)。您唯一知道的是它足够大,可以容纳值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并将其传递给具有类型转换的函数。

答案 2 :(得分:1)

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


我很确定,C99 bool已经推出(并且与所有其他基本值不同),因为前C99 BOOL不够好返回类型的函数:< / p>

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

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

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

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

  4. 因为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中的toBoolfromBool功能在CBoolBool之间进行转换。

魔法在#{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