Подтвердить что ты не робот

Что такое эквивалентный тип Haskell для C99 bool при использовании FFI?

У меня есть библиотека, которая использует тип данных C99 bool, и я хотел бы назвать ее через FFI.

Каков соответствующий тип для C99 bool в Haskell? В Foreign.C.types есть CInt, CShort и т.д., Но не CBool.

Если для bool нет "правильного" типа, какой безопасный альтернативный тип передается в функции, ожидающей bool?

Альтернативным подходом было бы изменение библиотеки C, но я хотел бы сохранить его в неприкосновенности.

4b9b3361

Ответ 1

Поскольку sizeof(_Bool) определяется реализацией на C99 (см. ИСО/МЭК 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.

Ответ 2

Насколько я знаю, C99 не определяет точный размер типа _Boolbool отображается на _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, по-видимому, сопоставляется с char в GCC. То, что вы увидите, зависит от вашего компилятора.

Из-за этого, я думаю, если вам нужна полная переносимость, вам лучше написать обертку для вашей функции C, которая примет простой int и передаст ее функции с типом cast.

Ответ 3

Существует разница между параметром bool as и типом результата bool.


Я уверен, что C99 bool был представлен (и отличается от всех других базовых значений), потому что pre-C99 BOOL не был достаточно хорошим возвращать тип функций:

В представлении такой переменной в памяти должно быть не менее 1 байт, но...

  • Обработка булевых элементов на уровне ассемблера выполняется с помощью зависимых от FLAG переходов. (см. && и ||)

  • Должно быть возможно использовать более быстрые побитовые и | вместо && и || на boolean, для которого bool должен быть 1 бит.

  • Возвращаемое значение функции должно иметь возможность использовать регистр FLAG (на некоторых машинах) вместо того, чтобы быть вынужденным использовать 1 бит регистра INT или даже использовать любой нуль/ненулевой int в регистре INT.

Из-за 3., IMHO, если мы не рассмотрим ABI (Application Binary Interface) для использования Bool C99 на каждой платформе, для этого не будет никакого прямого решения. Возможно, было бы проще исправить компилятор haskell, чтобы обернуть каждую импортированную/экспортированную функцию C, которая должна иметь/должна иметь тип результата C99-bool.


Если я правильно помню, int является безопасной альтернативой для большинства базовых типов C в параметре списка функции C. Но CChar, скорее всего, сделает то же самое (или лучше) для bool. Возможно, вам захочется прочитать об этом параметрическом параметре ,...), который используется printf.

Ответ 4

Если вы используете hsc2hs, вы можете просто сделать это:

#include <stdbool.h>

type CBool = #{type bool}

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

и вы также можете использовать функции toBool и fromBool в Foreign.Marshall.Utils для преобразования между CBool и Bool.

Магия находится в #{type bool}, которая сообщает hsc2hs выбрать числовой тип Haskell, который имеет тот же размер, что и тип C Bool. На моей машине это оказывается Word8.