我正在尝试动态加载和执行模块,
以下是我的代码
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
当我尝试运行该程序时,它会向我显示以下错误
[root@vps mypproj]# ./Main2
Main2: <command line>: module is not loaded: `TestModule' (./TestModule.hs)
不确定我缺少什么,有人可以帮我解决此错误
答案 0 :(得分:1)
我的想法是问题与你的路径有关,并且当程序无法加载“TestModule”时程序会默默地出错,然后抱怨模块没有加载。您是否尝试将execFnGhc与已加载的模块一起使用,并且您是否尝试过自然地加载GHC中的模块,例如Text.Parsec,然后在其中执行某些操作?
我会测试自己,但我没有在任何地方看到GHC.Paths库:/。
答案 1 :(得分:0)
我最近正在阅读相关的GHC源代码,看起来findModule
不适用于本地模块(在您的情况下为TestModule.hs
),除非它们已经加载。 (但它适用于远程包中的模块。)
要对编译模块进行GHCi样式动态加载,最好的办法是使用addTarget
和load
。正如评论中提到的,您还需要初始化会话动态标志。这是您的代码的工作版本:
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'
Target
的参数是什么?第一个是模块名称;第二个是我们是否应该被允许加载目标代码,或者总是解释模块;最后一个是可选的字符串缓冲区,您可以使用它来覆盖实际文件中的源代码(它是Nothing
因为我们不需要它。)
我是怎么想出来的?我查看了GHCi在GHC源代码中实现此代码的代码,以及compiler/main/GHC.hs
。我发现这是了解如何让GHC API做你想做的最可靠的方法。
混淆? GHC API的设计并不像增加......