2013-04-05 6 views
11

Ich versuche Modul dynamisch zu laden und auszuführen,ghc 7.4.2, dynamisch aufrufen Module

Unten ist mein Code

TestModule.hs

module TestModule 
     where 

evaluate = "Hello !!!" 

Invoke.hs

module Invoke 
     where 

import GHC 
import DynFlags 
import GHC.Paths (libdir) 
import Unsafe.Coerce (unsafeCoerce) 
import Data.Dynamic 

execFnGhc :: String -> String -> Ghc a 
execFnGhc modname fn = do 
     mod <- findModule (mkModuleName modname) Nothing 
     --setContext [IIModule mod] 
     GHC.setContext [ GHC.IIDecl $ (GHC.simpleImportDecl . GHC.mkModuleName $ modname) {GHC.ideclQualified = True} ] 
     value <- compileExpr (modname ++ "." ++ fn) 
     let value' = (unsafeCoerce value) :: a 
     return value' 

Main2.hs

import GHC.Paths (libdir) 
import GHC 
import Invoke 
-- import TestModule 

main :: IO() 
main = runGhc (Just libdir) $ do 
         str <- execFnGhc "TestModule" "evaluate" 
         return str 

Wenn ich versuche, das Programm auszuführen es mir zeigen, unter Fehler

[[email protected] mypproj]# ./Main2 
Main2: <command line>: module is not loaded: `TestModule' (./TestModule.hs) 

nicht sicher, was mir fehlt, kann mir bitte jemand diesen Fehler beheben helfen

+0

Ich weiß nicht viel darüber, aber es scheint, als ob Sie das viel einfacher mit den [plugins] (http: //hackage.haskell. org/Paket/Plugins) Paket. – Almanildo

Antwort

1

Mein Gedanke das Problem wäre hat etwas mit Ihrem Pfad zu tun, und dass das Programm im Hintergrund Fehler, wenn es "TestModule" nicht laden kann, dann beschwert sich, dass das Modul nicht geladen ist. Haben Sie versucht, execFnGhc mit einem bereits geladenen Modul zu verwenden, und haben Sie versucht, ein in GHC enthaltenes Modul wie Text.Parsec zu laden und dann etwas darin auszuführen?

Ich würde mich testen, aber ich sehe keine GHC.Paths-Bibliothek irgendwo: /.

+0

Ich probierte Listenlänge, str <- execFnGhc "Data.List" "Länge [1,2,3]", aber es wirft Ausnahme als "Main: Main: Panik! (Die 'unmöglich' ist passiert) (GHC-Version 7.4.2 für x86_64-unknown-linux): \t kein Paket Zustand noch: call GHC.setSessionDynFlags Bitte melden Sie dies als GHC Fehler: http://www.haskell.org/ghc/reportabug " – Xinus

+0

Von der Fehler, es sieht so aus, bevor Sie ExecFnGhc verwenden können, müssen Sie "Sitzungsflags" für GHC festlegen. Versuchen Sie sich die Art von GHC anzusehen.setSessionFlags und vielleicht sehen, ob "GHC.getSessionFlags" existiert; Es sieht so aus, als ob GHC mehr Informationen benötigt, bevor es Dinge aufrufen kann. –

0

Ich habe kürzlich den relevanten GHC-Quellcode gelesen, und es sieht so aus, als ob findModule nicht auf lokalen Modulen funktioniert (TestModule.hs in Ihrem Fall), es sei denn, sie wurden bereits geladen. (Es Module in Remote-Paketen funktioniert aber nicht.)

GHCi Stil dynamischen Laden von Modulen zusammengestellt zu tun, die beste Wahl ist addTarget und load zu verwenden. Wie in den Kommentaren erwähnt, müssen Sie auch die dynamischen Flags für die Sitzung initialisieren. Hier ist eine funktionierende Version Ihres Codes:

module Invoke 
     where 

import GHC 
import DynFlags 
import GHC.Paths (libdir) 
import Unsafe.Coerce (unsafeCoerce) 
import Data.Dynamic 

execFnGhc :: String -> String -> Ghc String 
execFnGhc modname fn = do 
     dflags <- getDynFlags 
     setSessionDynFlags dflags 
     let target = Target (TargetModule (mkModuleName modname)) True Nothing 
     addTarget target 
     load (LoadUpTo (mkModuleName modname)) 
     mod <- findModule (mkModuleName modname) Nothing 
     GHC.setContext [ GHC.IIDecl $ (GHC.simpleImportDecl . GHC.mkModuleName $ modname) {GHC.ideclQualified = True} ] 
     value <- compileExpr (modname ++ "." ++ fn) 
     let value' = (unsafeCoerce value) :: String 
     return value' 

Was sind die Parameter von Target? Der erste ist der Modulname; die zweite ist, ob wir Objektcode laden dürfen oder nicht, oder das Modul immer interpretieren; der letzte ist ein optionaler Zeichenfolgenpuffer, den Sie verwenden könnten, um den Quellcode in der tatsächlichen Datei zu überschreiben (es ist Nothing, weil wir das nicht brauchen.)

Wie habe ich das herausgefunden? Ich schaute auf den Code, den GHCi verwendet, um dies im GHC-Quellcode zu implementieren, sowie die compiler/main/GHC.hs. Ich habe festgestellt, dass dies der zuverlässigste Weg ist, um herauszufinden, wie Sie die GHC API dazu bringen können, das zu tun, was Sie wollen.

Verwirrend? Die GHC-API war nicht so sehr entworfen als akkretiert ...