18

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

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

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

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

4

5 回答 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 类型。

CBool我对缺席的猜测Foreign.C.Types是,底层的 C 实现预计不会支持 C99 的所有特性。一种非常广泛使用的编译器 (MSVC) 根本不支持 C99。

于 2013-03-12T19:00:20.950 回答
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似乎映射到charGCC 中。您将看到什么取决于您的编译器。

正因为如此,我认为,如果你想要完全的可移植性,你最好为你的 C 函数编写一个包装器,它将简单int地传递给具有类型转换的函数。

于 2013-03-12T18:59:12.070 回答
1

bool具有as 参数和具有bool结果类型之间存在差异。


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

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

  1. 在汇编器级别处理布尔值是通过 FLAG 相关的 goto 完成的。(见 && 和 ||)

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

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

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


如果我没记错的话,它是 C 函数参数列表中int大多数基本 C 类型的安全替代方案。但是 CChar 很可能也会对 bool 做同样的(或更好)。您可能想了解可变参数功能,它由.,...)printf

于 2013-03-21T15:38:10.063 回答
1

如果你使用hsc2hs,你可以这样做:

#include <stdbool.h>

type CBool = #{type bool}

cFalse, cTrue :: CBool
cFalse = 0
cTrue = 1

您还可以使用Foreign.Marshall.UtilstoBool中的andfromBool函数在and 之间进行转换。CBoolBool

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

于 2017-04-16T19:13:10.733 回答
0

baseForeign.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

于 2018-03-09T01:06:31.333 回答