2012-06-21 9 views
18

, ovvero è possibile incorporare il codice Haskell in una libreria C in modo che l'utente della libreria non debba sapere che Haskell è in uso? In particolare, in modo che l'utente possa utilizzare più librerie che incorporano Haskell, senza conflitti?È possibile incorporare Haskell in una libreria C opaco?

Per quanto comprendo le cose, si incorpora tra le chiamate a hs_init e hs_exit, ma queste implicano shenanigans dello stato globale e dovrebbero essere in conflitto con altre chiamate, no?

risposta

14

Sì, è possible chiamare il codice Haskell da C (e viceversa) tramite FFI, il Foreign Function Interface. Purtroppo, come il haskell.org docs dice, non è possibile evitare le chiamate per inizializzare e finalizzare l'ambiente Haskell:

La chiamata a hs_init() inizializza sistema runtime di GHC. NON provare a invocare qualsiasi funzione di Haskell prima di chiamare hs_init(): le cose cattive saranno senza dubbio.

Ma, this è interessante anche:

Non ci possono essere più chiamate a hs_init(), ma ognuno dovrebbe essere di pari passo con una (e una sola) chiamata per hs_exit()

E furthermore:

le specifiche FFI richiede l'implementazione per supportare la reinizializzazione dello stesso dopo essere stato arrestato con hs_exit(), ma attualmente GHC non supporta lo standard .

Fondamentalmente la mia idea è che si può sfruttare questa specifiche al fine di scrivere portarvi direttamente una classe wrapper C++ che gestisce le chiamate a hs_init e hs_exit per voi, a esempio utilizzando metodi template circondati da hs_init e hs_exit che si può eseguire l'override utilizzando qualsiasi chiamata haskell desiderata. Tuttavia, fai attenzione alle interazioni con altre librerie che chiamano il codice haskell: i livelli nidificati di chiamate a hs_init e hs_exit devono essere corretti (quindi è sicuro utilizzare librerie che li chiamano tra i wrapper), ma il numero totale di chiamate deve sempre corrispondere, il che significa che se quelle librerie inizializzano solo l'ambiente senza cercare di chiuderlo, allora sta a te completare il lavoro.

Un altro (probabilmente migliore) idea, senza sfruttare eredità e prioritario, può essere quello di avere una semplice classe che chiama HaskellEnvhs_init nel costruttore e hs_exit nel distruttore. Se li si dichiarano come variabili automatiche, si otterrà che le chiamate a hs_init e hs_exit corrisponderanno sempre e l'ultima chiamata a hs_exit verrà effettuata non appena l'ultimo oggetto HaskellEnv viene distrutto quando si lascia l'ambito. Dai un'occhiata allo this question per evitare la creazione di oggetti nello heap (potrebbero essere pericolosi in questo caso).

+0

So già che è possibile. Voglio sapere se è possibile farlo _safely_. –

+0

Devi solo stare attento nel chiamare 'hs_init' e' hs_exit', suppongo.Puoi provare a codificare le classi C++ del wrapper per avvolgere quelle chiamate in modo sicuro, ma dipende da te. Il primo modo che mi viene in mente è usare i metodi template circondati da 'hs_init' e' hs_exit' che puoi sovrascrivere usando qualsiasi chiamata haskell che vuoi. –

+0

È perfettamente accettabile e utilizzato in alcuni sistemi di grandi dimensioni. –

Problemi correlati