2013-03-12 10 views
18

Mam bibliotekę, która korzysta z typu danych C99 bool i chciałbym ją nazwać przez FFI.Co to jest odpowiednik typu Haskell dla C99 bool podczas korzystania z FFI?

Jaki jest odpowiedni typ dla C99 bool w Haskell? W Foreign.C.types są CInt, CShort itp., Ale bez CBool.

Jeśli nie ma "prawidłowego" typu dla bool, jaki jest bezpieczny alternatywny typ przekazywany w funkcji oczekującej na bool?

Alternatywnym podejściem byłoby zmodyfikowanie biblioteki C, ale chciałbym ją zachować w stanie nienaruszonym.

+0

skończyło się na modyfikację biblioteki korzystać ints zamiast bools. Była to wewnętrzna biblioteka, więc łatanie łatwa. W każdym razie jest to interesujący problem sam w sobie. Mam nadzieję, że biblioteka podstawowa może zostać rozszerzona o wsparcie boolowe w przyszłości. – Zouppen

Odpowiedz

12

Od sizeof(_Bool) jest zdefiniowany w implementacji w C99 (patrz ISO/IEC 9899: 1999 6.2.5, 6.2.6 i 6.5.3.4/4), oczywistym przenośnym rozwiązaniem jest wywoływanie takich funkcji poprzez opakowania, które używają int z bool. Ewentualnie, jeśli nie zależy Ci na przenośności, możesz sprawdzić dokumentację swojego kompilatora, aby dowiedzieć się, co to jest sizeof(_Bool) na twojej platformie i użyć odpowiedniego typu FFI.

Moje przypuszczenie z powodu CBool nieobecności w Foreign.C.Types jest to, że podstawowa implementacja C nie ma obsługiwać wszystkich funkcji C99. Jeden bardzo szeroko stosowany kompilator (MSVC) w ogóle nie obsługuje C99.

+0

Nie wiem, czy to ma sens jako powód. Oczywiście "CBool" będzie użyty tylko w połączeniu z kodem C, który użył 'bool', w takim przypadku zakładasz istnienie zgodnego kompilatora.Spodziewam się, że bardziej prawdopodobnym powodem jest to, że 'CBool' jest bardziej niejasny i rzadziej używany, więc nikt nie potrzebował jeszcze pisać wsparcia. –

+0

Ponieważ jest to * zdefiniowane przez implementację * może mieć dowolny rozmiar, nawet w kompilatorze zgodnym z C99 - i może się różnić w zależności od kompilatora. Jakikolwiek FFI do C byłby trudny do wymyślenia automagicznie i * bezpiecznie *, a Haskell FFI nie jest wyjątkiem. – jpaugh

+0

@jpaugh No cóż, 'sizeof (int)' jest również zdefiniowany przez implementację w C. Możemy jednak wywoływać funkcje o parametrach 'int' od Haskella, ponieważ C ABI dla platformy docelowej jest określone przez dostawcę platformy. Problem polega na tym, że niektórzy dostawcy ignorują rozszerzenia C99. Rozsądnym rozwiązaniem byłoby potraktowanie "_Bool" podobnie jak "unsigned char" w tych przypadkach. –

2

O ile mi wiadomo, C99 nie określa dokładnej wielkości _Bool typu (i bool jest odwzorowywany _Bool). Jedyną rzeczą, o której wiesz, że jest wystarczająco duży, aby pomieścić wartości 0 i 1. Więc jego binarna reprezentacja jest zależna od kompilatora, dlatego, jak sądzę, nie jest obecna w bibliotece wsparcia FFI.

Poniższy program jest skompilowany z GCC 4.7.2:

#include <stdio.h> 
#include <stdbool.h> 

int main() { 
    printf("%d", sizeof(bool)); 
    return 0; 
} 

daje następujący wynik:

% gcc -std=c99 -o test test.c 
% ./test 
1  

Więc bool wydaje się być odwzorowywane char w GCC. To, co zobaczysz, zależy od twojego kompilatora.

Z tego powodu, myślę, że jeśli chcesz mieć pełną przenośność, lepiej napisz wrapper dla funkcji C, która przyjmie zwykły numer int i przekaże go do funkcji z rzutowaniem typu.

+4

Po tym samym rozumowaniu, żadne z 'CInt',' CLong' nie istnieje, ponieważ te nie mają również wymagań dotyczących dokładnego rozmiaru. Wszystko, co wiemy na przykład o 'int' jest to, że musi przynajmniej obsługiwać wartości od -32767 do 32767. –

+1

@LucDanton, podstawowe typy dla' CInt' i 'CLong' są jednak obsługiwane przez ** wszystkie ** kompilatory, bez wyjątków. Nie można tego powiedzieć o 'bool', ponieważ jest to rozszerzenie C99, a niektóre z najczęściej używanych kompilatorów nie obsługują w ogóle C99. Oczywiście, przyzwoita implementacja FFI nie powinna polegać na istnieniu idealnego kompilatora wspierającego wszystkie najnowsze standardy. –

+3

To powinno być odpowiedzią, a nie tym, co wkładasz. Moja uwaga była retorycznym narzędziem do wykazania wady argumentacji. –

1

Istnieje różnica między wartością parametru bool i typem wyniku bool.


Jestem pewien, pewny, że C99 bool został wprowadzony (i różni się od wszystkich innych podstawowych wartości), ponieważ pre-C99 BOOL nie był wystarczająco dobry powrót rodzaj funkcji:

Nie musi istnieć in-memory-reprezentację takiej zmiennej, co najmniej 1 bajt, ale ...

  1. manipulowanie logicznych na poziomie asemblera odbywa się poprzez FLAG zależne GOTOS.(Patrz & & i ||)

  2. Powinno być możliwe użycie szybsze bitowe & i | zamiast & & i || na booleans, który potrzebuje bool być 1 bit.

  3. zwrotna wartość funkcji powinna być w stanie wykorzystywać rejestr flagi (w niektórych pralkach) zamiast zapychanie zmuszony użyć 1 bit rejestru INT, lub wykorzystywać dowolny zero/niezerową int w INT zarejestrować.

powodu 3., IMHO, chyba że weźmiemy pod uwagę ABI (Application Binary Interface) z wykorzystaniem C99 bool na każdej platformie, nie będzie żadnego bezpośredniego rozwiązanie tego problemu. Łatwiej jest załatać kompilator haskell, aby zawinąć każdą zaimportowaną/wyeksportowaną funkcję C, która ma/powinna mieć typ wyniku C99-bool.


Jeśli dobrze pamiętam, int jest bezpieczną alternatywą dla większości podstawowych typów C w parametru listy funkcji C. Ale CChar najprawdopodobniej zrobi to samo (lub lepiej) dla boola. Możesz przeczytać informacje o tym parametrze parametru wariasu ,...), który jest używany przez printf.

1

Jeśli używasz hsc2hs, można po prostu to zrobić:

#include <stdbool.h> 

type CBool = #{type bool} 

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

można także korzystać z funkcji toBool i fromBool w Foreign.Marshall.Utils do konwersji pomiędzy CBool i Bool.

Magia jest w #{type bool}, która mówi hsc2hs, aby wybrać numeryczny typ Haskell, który ma taki sam rozmiar jak typ C bool. Na moim komputerze okazuje się, że jest to Word8.

Powiązane problemy