【问题标题】:ghc 7.4.2, Dynamically calling modulesghc 7.4.2,动态调用模块
【发布时间】:2013-03-27 07:51:03
【问题描述】:

我正在尝试动态加载和执行模块,

下面是我的代码

TestModule.hs

module TestModule
        where

evaluate = "Hello !!!"

调用.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)

不知道我错过了什么,有人可以帮我解决这个错误

【问题讨论】:

  • 我对此知之甚少,但您似乎可以使用 plugins 包更轻松地做到这一点。

标签: haskell ghc dynamic-loading


【解决方案1】:

我的想法是问题与您的路径有关,并且程序在无法加载“TestModule”时会默默地出错,然后抱怨模块未加载。您是否尝试过将 execFnGhc 与已加载的模块一起使用,并且您是否尝试过加载自然存在于 GHC 中的模块,例如 Text.Parsec,然后在其中执行某些操作?

我会测试自己,但我在任何地方都看不到 GHC.Paths 库:/。

【讨论】:

  • 我尝试了 list length, str haskell.org/ghc/reportabug"
  • 从错误来看,在您可以使用 execFnGhc 之前,您需要为 GHC 设置“会话标志”。尝试查看 GHC.setSessionFlags 的类型,并可能查看“GHC.getSessionFlags”是否存在;看起来 GHC 需要更多信息才能调用事物。
【解决方案2】:

我最近正在阅读相关的 GHC 源代码,看起来 findModule 不适用于本地模块(在您的情况下为 TestModule.hs),除非它们已经被加载。 (不过,它适用于远程包中的模块。)

要对编译的模块进行 GHCi 风格的动态加载,最好的办法是使用 addTargetload。正如 cmets 中提到的,您还需要初始化会话动态标志。这是您的代码的工作版本:

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 与其说是设计的不如说是增加的...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多