24

我有一个现有的 Haskell 函数,它使用 GHC API 从模块中动态加载已编译的代码。它基于博文Dynamic Compilation and Loading of Modules in Haskell 中的代码。

该代码在 GHC 7.0 中运行良好,但必须稍作修改才能在 GHC 7.2 中编译,因为 GHC API 发生了变化。

该代码现在在 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)中在线获取。

有谁知道如何解决或解决这个问题?

另外,这可能是由 GHC 7.2 中的新 Safe Haskell 更改引起的,还是仅仅是由于对 GHC API 的修改?

4

2 回答 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

PS:改用它可能是个好主意GHC.dynCompileExpr,这样你就可以避免unsafeCoerce. 您必须在上下文中添加一个合格的 import forData.Dynamic才能使其工作,但Data.Dynamic.Dynamic通常使用一个值更好,因为您可以更优雅地处理类型错误。我已经在上面的代码中添加了代码作为注释。


更新

这是 GHC 7.4.1 的语法:

GHC.setContext  
  -- import qualified Module
  [ GHC.IIDecl $ 
    (GHC.simpleImportDecl . GHC.mkModuleName $ moduleName)
    {GHC.ideclQualified = True}
  ]
于 2012-02-14T02:40:08.260 回答
0

尝试

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

(来自另一个 StackOverflow 问题

于 2012-02-11T09:42:54.713 回答