2012-02-08 10 views
23

मेरे पास एक मौजूदा हास्केल फ़ंक्शन है जो मॉड्यूल से संकलित कोड को गतिशील रूप से लोड करने के लिए जीएचसी एपीआई का उपयोग करता है। यह ब्लॉग पोस्ट Dynamic Compilation and Loading of Modules in Haskell से कोड पर आधारित है।जीएचसी एपीआई - जीएचसी 7.2 का उपयोग कर संकलित मॉड्यूल से हास्केल कोड को गतिशील रूप से कैसे लोड करें?

कोड जीएचसी 7.0 में ठीक काम करता है, लेकिन जीएचसी 7.2 में संकलित करने के लिए थोड़ा संशोधित होना था, क्योंकि जीएचसी एपीआई बदल गई थी।

कोड अब GHC 7.2 में एक रनटाइम त्रुटि फेंकता है:

mkTopLevEnv: not a home module (module name):(function name) 

कोड,

evalfuncLoadFFI String moduleName, 
       String externalFuncName, 
       String internalFuncName = do 

    result <- liftIO $ defaultRunGhc $ do 
    dynflags <- GHC.getSessionDynFlags 
    _ <- GHC.setSessionDynFlags dynflags 
    m <- GHC.findModule (GHC.mkModuleName moduleName) Nothing 

--------------------------------------------------------  
-- The following code works fine in GHC 7.0.4: 
-- 
-- GHC.setContext [] [(m, Nothing)] 
-- 
-- This new code attempts to set context to the module, 
-- but throws an error in GHC 7.2: 
-- 
    (_,oi) <- GHC.getContext 
    GHC.setContext [m] oi 
-------------------------------------------------------- 

    fetched <- GHC.compileExpr (moduleName ++ "." ++ externalFuncName) 
    return (Unsafe.Coerce.unsafeCoerce fetched :: [LispVal] -> IOThrowsError LispVal) 
    defineVar env internalFuncName (IOFunc result) 

संदर्भ के लिए है पूरा कोड FFI.hs (github.com) में ऑनलाइन उपलब्ध है।

क्या किसी को भी इस समस्या को ठीक करने या काम करने का कोई विचार है?

इसके अलावा, क्या यह जीएचसी 7.2 में नए सुरक्षित हास्केल परिवर्तनों के कारण हो सकता है, या यह सिर्फ जीएचसी एपीआई में संशोधन के कारण है?

उत्तर

14

वर्तमान मॉड्यूल संदर्भ जब आप संदर्भ में मॉड्यूल निर्दिष्ट मॉड्यूल है कि वर्तमान में संकलित किया जा रहा है, यानी के लिए आरक्षित है, वे स्पष्ट रूप से नहीं होना चाहिए बाहरी।

इसके बजाय, आपको setContext के दूसरे तर्क में, आयात के रूप में वांछित मॉड्यूल निर्दिष्ट करना चाहिए। यह बहुत की तरह किया जा सकता है:

GHC.setContext [] 
    -- import qualified Module 
    [ (GHC.simpleImportDecl . GHC.mkModuleName $ moduleName) 
    { GHC.ideclQualified = True 
    } 
    -- -- import qualified Data.Dynamic 
    -- , (GHC.simpleImportDecl . GHC.mkModuleName $ "Data.Dynamic") 
    -- { GHC.ideclQualified = True 
    -- } 
    ] 
fetched <- GHC.compileExpr $ moduleName ++ "." ++ externalFuncName 
return . unsafeCoerce $ fetched 
-- or: 
-- fetched <- GHC.dynCompileExpr $ moduleName ++ "." ++ externalFuncName 
-- return . fromDynamic (error "Illegal type cast") $ fetched 

पुनश्च: यह एक अच्छा विचार के बजाय GHC.dynCompileExpr उपयोग करने के लिए हो सकता है, ताकि आप unsafeCoerce बच सकते हैं। आपको काम करने के संदर्भ में Data.Dynamic के लिए एक योग्य आयात जोड़ना होगा, लेकिन Data.Dynamic.Dynamic मान आमतौर पर काम करने के लिए अच्छा है, क्योंकि आप टाइप त्रुटियों को और अधिक गहन तरीके से संभाल सकते हैं। मैंने उपरोक्त कोड में टिप्पणियों के रूप में कोड जोड़ा है।


अद्यतन

और यहाँ GHC 7.4.1 के लिए वाक्य रचना है:

GHC.setContext 
    -- import qualified Module 
    [ GHC.IIDecl $ 
    (GHC.simpleImportDecl . GHC.mkModuleName $ moduleName) 
    {GHC.ideclQualified = True} 
    ] 
+0

यह पूरी तरह से काम किया। उचित वाक्यविन्यास और विस्तृत स्पष्टीकरण के लिए धन्यवाद! अपने बक्षीस का आनंद लें :) –

+2

मैंने जीएचसी 7.4.1 के लिए वाक्यविन्यास भी जोड़ा है यदि यह किसी और को लाभ पहुंचा सकता है। –

0

प्रयास करें

GHC.setContext [] [(m,Nothing)] 

(another StackOverflow question से)

+1

मेरी हाल ही में संपादित देखें; यह वह कोड है जिसका मैं जीएचसी 7.0 के लिए उपयोग कर रहा हूं। लेकिन एपीआई जीएचसी 7.2 और 7.4 में बदल गया ... –

संबंधित मुद्दे