2015-07-03 9 views
42

Vorrei utilizzare una libreria esterna, RDFox, in un progetto Haskell.Come utilizzare una DLL in un progetto Haskell?

Contesto: Sto lavorando su Windows e Linux, entrambi a 64 bit, utilizzando GHC 7.10 e stack. RDFox è programmato in C++. Le librerie condivise di RDFox (.dll, .so) possono essere scaricate con i wrapper Java e Python.

Obiettivo: Vorrei riutilizzare le librerie compilate da RDFox (.dll, .so) nel mio progetto in Haskell, quindi ho bisogno di creare un wrapper per Haskell RDFox.

Problemi: Essendo relativamente nuovo per Haskell, ho difficoltà a sapere da dove iniziare. Ho trovato diverse pagine sull'argomento (da Haskell wiki e StackOverflow), ma il flusso di lavoro e la configurazione non mi sono chiari.

Domande: vorrei sapere:

  1. Come configurare stack e cabala di utilizzare librerie esterne, per costruire su Windows o Linux (macchine differenti, stesso repository).
  2. Come configurare GHCi per i test interattivi su questa libreria esterna.
  3. È la traduzione del wrapper Python per Haskell il modo migliore per andare? Vorrei evitare l'analisi del codice RDFox C++.
+1

Per prima cosa è probabilmente necessario creare un wrapper C-export per l'API C++. – alternative

+0

Non è possibile creare direttamente il wrapper in Haskell? Voglio dire, se devo creare un wrapper C e poi uno Haskell, qual è il punto? –

+1

Le convenzioni di denominazione in C++ sono molto più complicate rispetto a C. Non credo che FFI supporti il ​​nome di mangling per cose non esterne a C. – alternative

risposta

0

Risposta da this documentation:

ghc -c Adder.hs 
ghc -c StartEnd.c 
ghc -shared -o Adder.dll Adder.o Adder_stub.o StartEnd.o 
1
  1. Avrete bisogno di usare extra-lib-dirs e extra-libraries nella sezione executable del file .cabal in questo modo:

    name:     MyApp 
    version:    0.1.0.0 
    synopsis: 
    homepage: 
    author:    simon.bourne 
    category: 
    build-type:   Simple 
    cabal-version:  >=1.10 
    
    library 
        exposed-modules:  HelloWorld 
        build-depends:  base >= 4.7 && < 5 
        hs-source-dirs:  src 
        default-language:  Haskell2010 
    
    executable MyApp 
        main-is:    Main.hs 
        extra-lib-dirs:  lib 
        extra-libraries:  helloWorld 
        build-depends:  base >= 4.7 && < 5, 
             MyApp 
        hs-source-dirs:  app 
    
    default-language: Haskell2010 
    

    Put la tua DLL e .so in lib. Stai attento, ti imbatterai in problemi di ordine dei collegamenti se utilizzi una libreria statica (.a anziché .so) su linux.

    Vedere this per un esempio. Non farti ingannare dal nome in quanto funziona bene con i file .so.

  2. stack ghci dovrebbe funzionare solo se è possibile trovare la libreria (LD_LIBRARY_PATH su linux).

  3. L'API C (menzionata nei commenti sulla tua domanda) è già lì. Hai solo bisogno di scrivere le firme Haskell FFI, per esempio:

    foreign import ccall safe "helloWorld" c_helloWorld :: IO() 
    

    mi piacerebbe molto caldamente utilizzando safe ccalls, e Non avvolgere le funzioni in unsafePerformIO.

    Se è necessario passare strutture non opache, è possibile esaminare c2hs o hsc2hs, ma non credo che sarà necessario.Vedi questo question per maggiori dettagli.

1

È necessario creare un wrapper C-esportato per l'API C++ e Haskell wrapper per FFI di involucro C-esportato.

Marshalling tra C# e Haskell descritto qui: Calling Haskell from C#

ma marshalling molto simili tra C++ e Haskell

Ad esempio, creare C++ funzione di esportazione:

extern "C" __declspec(dllexport) int __cdecl addFive(int number); 

extern "C" __declspec(dllexport) int __cdecl addFive(int number) 
{ 
    return number + 5; 
} 

In Haskell è necessario codice di importazione:

foreign import ccall "addFive" addFive :: Int -> Int 

Quindi è possibile utilizzare addFive in Haskell come tipica funzione Haskell

Per i tipi di dati compbound (classi e strutture) è necessario creare un analogo di tipo dati C++ in Haskell. Quindi è necessario descrivere come i tipi di dati di marshall da C++ a Haskell e da Haskell a C++.

In Haskell significa che è necessario creare un'istanza Storable per i propri tipi di dati.

Problemi correlati