tipos - string en haskell
¿Cuál es el tipo de Haskell equivalente para C99 bool cuando se usa FFI? (5)
Dado que sizeof(_Bool)
está definido por la implementación en C99 (consulte ISO / IEC 9899: 1999 6.2.5, 6.2.6 y 6.5.3.4/4), la solución portátil obvia es llamar a tales funciones a través de envoltorios que usan int
lugar de bool
Alternativamente, si no le importa la portabilidad, puede consultar la documentación de su compilador para averiguar qué es sizeof(_Bool)
en su plataforma y usar el tipo de FFI correspondiente.
Supongo que por la razón de que CBool
esté ausente en Foreign.C.Types
es que no se espera que la implementación de C subyacente sea compatible con todas las características de C99. Un compilador muy utilizado (MSVC) no admite C99 en absoluto.
Tengo una biblioteca que utiliza el tipo de datos bool
C99 y me gustaría llamarlo a través de FFI.
¿Cuál es el tipo correspondiente para C99 bool en Haskell? En Foreign.C.types hay CInt, CShort, etc., pero no CBool.
Si no hay un tipo "correcto" para bool
, ¿cuál es el tipo alternativo seguro que se pasa en una función que espera un bool
?
Un enfoque alternativo sería modificar la biblioteca C, pero me gustaría mantenerla intacta.
Hay una diferencia entre tener un bool
como parámetro y tener un tipo de resultado bool
.
Estoy seguro de que se introdujo Bool de C99 (y es diferente de todos los demás valores básicos), porque el BOOL pre-C99 no era un tipo de funciones de retorno suficientemente bueno:
Debe existir una representación en memoria de dicha variable, al menos 1 byte, pero ...
El manejo de booleanos a nivel de ensamblador se realiza a través de gotos dependientes de FLAG. (ver && y ||)
Debería ser posible usar el bitwise más rápido & y | en lugar de && y || en booleanos, que necesita que el bool sea de 1 bit.
El valor de retorno de una función debería poder usar el registro FLAG (en algunas máquinas) en lugar de ser forzado a usar 1 bit de un registro INT o incluso usar cualquier int cero / cero en un registro INT.
Debido a 3., IMHO, a menos que consideremos el ABI (Application Binary Interface) del uso de bools C99 en cada plataforma, no habrá ninguna solución directa para esto. Podría ser más fácil parchear el compilador haskell para envolver cada función C importada / exportada que tenga / debería tener el tipo de resultado C99-bool.
Si recuerdo correctamente, int
es la alternativa segura para la mayoría de los tipos C básicos en la lista de parámetros de una función C. Pero CChar probablemente hará lo mismo (o mejor) para bool, también. Es posible que desee leer acerca de la función de parámetro variadic ,...)
, que es usada por printf
.
La biblioteca base
tiene Foreign.C.Types.CBool
partir de la versión 4.10.0.0
, que corresponde a ghc-8.2
.
https://hackage.haskell.org/package/base-4.10.1.0/docs/Foreign-C-Types.html#t:CBool
Que yo sepa, C99 no define el tamaño exacto del tipo _Bool
(y bool
se asigna a _Bool
). Lo único que se sabe al respecto es que es lo suficientemente grande como para contener los valores 0
y 1
. Entonces, su representación binaria es dependiente del compilador, por eso, supongo, no está presente en la biblioteca de soporte de FFI.
El siguiente programa, compilado con GCC 4.7.2:
#include <stdio.h>
#include <stdbool.h>
int main() {
printf("%d", sizeof(bool));
return 0;
}
Da la siguiente salida:
% gcc -std=c99 -o test test.c
% ./test
1
Entonces, bool
parece estar asignado a char
en GCC. Lo que verás dependerá de tu compilador.
Debido a esto, creo que si desea una portabilidad completa, es mejor que escriba una envoltura para su función C, que tomará el int
simple y la pasará a la función con un tipo de conversión.
Si usa hsc2hs , puede hacer esto:
#include <stdbool.h>
type CBool = #{type bool}
cFalse, cTrue :: CBool
cFalse = 0
cTrue = 1
y también puede usar las funciones toBool
y fromBool
en Foreign.Marshall.Utils para convertir entre CBool
y Bool
.
La magia está en #{type bool}
, que le dice a hsc2hs
que elija un tipo numérico de Haskell que sea del mismo tamaño que el tipo bool
C. En mi máquina, esto resulta ser Word8
.