Jus*_*ier 24 haskell module dynamic-loading ghc ghc-api
我有一个现有的Haskell函数,它使用GHC API动态加载模块中的编译代码.它基于Haskell博客文章动态编译和模块加载的代码.
代码在GHC 7.0中运行良好,但必须稍加修改才能在GHC 7.2中编译,因为GHC API发生了变化.
代码现在在GHC 7.2中引发运行时错误:
mkTopLevEnv: not a home module (module name):(function name)
Run Code Online (Sandbox Code Playgroud)
代码是
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)
Run Code Online (Sandbox Code Playgroud)
作为参考,完整代码可在FFI.hs(github.com)在线获得.
有没有人知道如何解决或解决这个问题?
另外,这可能是由于GHC 7.2中新的Safe Haskell更改引起的,还是仅仅是因为修改了GHC API?
dfl*_*str 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
Run Code Online (Sandbox Code Playgroud)
PS:使用它可能是一个好主意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}
]
Run Code Online (Sandbox Code Playgroud)