hsc2hs: mutar una estructura C con Haskell
Estoy tratando de escribir un programa Haskell que se comunique con C (en última instancia para iOS a través de GHC-iOS). Quiero que pase una cadena de C a Haskell, haga que Haskell lo procese y luego devuelva algunos tipos de datos de Haskell a C Structs a través de hsc2s. No he podido encontrar un tutorial claro y simple. Lo único que Haskell necesita de C es la Cadena, nada más.
No tengo problemas con la primera parte, pasarle una cuerda a Haskell.
testPrint :: CString -> IO ()
testPrint c = do
s <- peekCString c
putStrLn s
Para fines de prueba y referencia futura, solo quiero poder manejar algo como lo siguiente.
C estructura
struct testdata {
char *a;
char *b;
int c;
};
Tipo de datos Haskell
data TestData = TestData {
a :: String,
b :: String,
c :: Int
} deriving Show
-- not sure what the type would look like
testParse :: CString -> TestData
Entiendo que necesito escribir la clase TestData como Almacenable e implementar peek, poke, sizeOf y alineación, pero necesito ver un ejemplo simple antes de que realmente pueda entenderlo. La mayoría de los tutoriales requieren bibliotecas externas y lo hacen más complicado de lo que debe ser.
Aquí están los recursos que he visto:
Stackoverflow - ¿Cómo usar hsc2hs para enlazar constantes, funciones y estructuras de datos?
Haskell Cafe: FFI para principiantes
Escribir interfaces de Haskell en código C: hsc2hs
Editar: actualmente donde estoy atascado (aparece un error de segmentación cuando se llama a setFoo en C)
Fragmento de código Haskell
instance Storable Foo where
sizeOf = #{size foo}
alignment = alignment (undefined :: CString)
poke p foo = do
#{poke foo, a} p $ a foo
#{poke foo, b} p $ b foo
#{poke foo, c} p $ c foo
peek p = return Foo
`ap` (#{peek foo, a} p)
`ap` (#{peek foo, b} p)
`ap` (#{peek foo, c} p)
foreign export ccall "setFoo" setFoo :: Ptr Foo -> IO ()
setFoo :: Ptr Foo -> IO ()
setFoo f = do
newA <- newCString "abc"
newB <- newCString "def"
poke f (Foo newA newB 123)
Fragmento de código C
foo *f;
f = malloc(sizeof(foo));
foo->a = "bbb"
foo->b = "aaa"
foo->c = 1
// this is incorrect
// setFoo(&f);
// this is correct
setFoo(f);