简体   繁体   English

GHC API - 如何使用GHC 7.2从已编译的模块动态加载Haskell代码?

[英]GHC API - How to dynamically load Haskell code from a compiled module using GHC 7.2?

I have an existing Haskell function that uses the GHC API to dynamically load compiled code from a module. 我有一个现有的Haskell函数,它使用GHC API动态加载模块中的编译代码。 It is based on the code from the blog post Dynamic Compilation and Loading of Modules in Haskell . 它基于Haskell博客文章动态编译和模块加载的代码。

The code works fine in GHC 7.0, but had to be slightly modified to compile in GHC 7.2, because the GHC API changed. 代码在GHC 7.0中运行良好,但必须稍加修改才能在GHC 7.2中编译,因为GHC API发生了变化。

The code now throws a runtime error in GHC 7.2: 代码现在在GHC 7.2中引发运行时错误:

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

The code is 代码是

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)

For reference, the full code is available online in FFI.hs (github.com) . 作为参考,完整代码可在FFI.hs(github.com)在线获得。

Does anyone have any idea how to fix or work around this problem? 有没有人知道如何解决或解决这个问题?

Also, could this be caused by the new Safe Haskell changes in GHC 7.2, or is it just due to modifications to the GHC API? 另外,这可能是由于GHC 7.2中新的Safe Haskell更改引起的,还是仅仅是因为修改了GHC API?

The current module context is reserved for modules that are currently being compiled, ie when you specify modules in the context, they must explicitly not be external. 当前模块上下文保留给当前正在编译的模块,即当您在上下文中指定模块时,它们必须明确不是外部的。

Instead, you should specify the wanted module as an import, in the second argument of setContext . 相反,您应该在setContext的第二个参数中将所需模块指定为导入。 This can be done like so: 这可以这样做:

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 : it might be a good idea to use GHC.dynCompileExpr instead, so that you can avoid the unsafeCoerce . PS :使用GHC.dynCompileExpr可能是个好主意,这样你就可以避免使用unsafeCoerce You must add a qualified import for Data.Dynamic in the context for it to work, but a Data.Dynamic.Dynamic value is generally nicer to work with, since you can handle type errors more gracefully. 您必须在上下文中为Data.Dynamic添加合格的导入才能使用它,但Data.Dynamic.Dynamic值通常可以更好地使用,因为您可以更优雅地处理类型错误。 I've added the code for that as comments in the above code. 我在上面的代码中添加了代码作为注释。


Update 更新

And here is the syntax for GHC 7.4.1: 这是GHC 7.4.1的语法:

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

Try 尝试

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

(from another StackOverflow question ) (来自另一个StackOverflow问题

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM