Sto provando a scrivere un programma Haskell che comunica con C (in definitiva per iOS tramite GHC-iOS). Voglio che passi una stringa da C a Haskell, che Haskell lo elabori e poi restituisca alcuni tipi di dati da Haskell a C Structs tramite hsc2s. Non sono riuscito a trovare un tutorial chiaro e semplice. L'unica cosa di cui Haskell ha bisogno da C è String, nient'altro.hsc2hs: Mutate una struttura C con Haskell
Non ho alcun problema con la prima parte, passando una stringa ad Haskell.
testPrint :: CString -> IO()
testPrint c = do
s <- peekCString c
putStrLn s
Per scopi di test e riferimento futuro, voglio solo essere in grado di gestire qualcosa di simile alla seguente.
C struct
struct testdata {
char *a;
char *b;
int c;
};
Haskell Tipo di dati
data TestData = TestData {
a :: String,
b :: String,
c :: Int
} deriving Show
-- not sure what the type would look like
testParse :: CString -> TestData
ho capito che ho bisogno di typeclass TestData come riponibile e implementare peek, poke, sizeOf e l'allineamento, ma ho bisogno di vedere un semplice esempio prima che io possa davvero capirlo. La maggior parte delle esercitazioni richiede librerie esterne e la rendono più complicata di quanto non debba essere.
Qui ci sono le risorse che ho guardato:
Stackoverflow - How to use hsc2hs to bind to constants, functions and data structures?
Haskell Cafe - FFI for a beginner
Writing Haskell interfaces to C code: hsc2hs
Edit: Attualmente dove mi sono bloccato (ottiene l'errore di segmentazione quando setFoo è chiamato in C)
codice Haskell frammento
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)
C frammento di codice
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);
ho lavorato attraverso il primo e il quarto collegamento. Il problema a cui sto lavorando ora è come esportare una funzione che restituisce 'TestData' a C. Penso che abbia bisogno di assomigliare a' testParse :: CString -> IO (Ptr TestData) 'ma non sono sicuro di come avvolgere TestData in un Ptr. Ho già un'istanza memorizzabile per TestData. – MCH
Ottenuto per la compilazione con 'testParse :: CString -> IO (StablePtr TestData)' ma sto ottenendo un errore di segmentazione in C. Forse è il modo in cui ho impostato Storable. Pubblicherò il codice più tardi. – MCH
hai provato a cercare nel codice sorgente delle associazioni Haskell FFI C esistenti? Sono abbastanza sicuro che non è la prima volta che viene tentata qualcosa del genere. –