动态加载已编译的Haskell模块 - GHC 7.6

12

我正在尝试使用GHC API动态编译和加载Haskell模块。我了解API在不同版本间有相当大的波动,因此我特别针对GHC 7.6.* 进行讨论。

我尝试在MacOS和Linux上运行相同的代码。在两种情况下,Plugin模块编译顺利,但在加载时会出现以下错误:Cannot add module Plugin to context: not interpreted

问题类似于这里的内容,其中模块仅在与主程序相同的运行中编译时才会加载。

-- Host.hs: compile with ghc-7.6.*
-- $ ghc -package ghc -package ghc-paths Host.hs
-- Needs Plugin.hs in the same directory.
module Main where

import GHC
import GHC.Paths ( libdir )
import DynFlags
import Unsafe.Coerce

main :: IO ()
main =
    defaultErrorHandler defaultFatalMessager defaultFlushOut $ do
      result <- runGhc (Just libdir) $ do
        dflags <- getSessionDynFlags
        setSessionDynFlags dflags
        target <- guessTarget "Plugin.hs" Nothing
        setTargets [target]
        r <- load LoadAllTargets
        case r of
          Failed    -> error "Compilation failed"
          Succeeded -> do
            setContext [IIModule (mkModuleName "Plugin")]
            result <- compileExpr ("Plugin.getInt")
            let result' = unsafeCoerce result :: Int
            return result'
      print result

而插件:

-- Plugin.hs
module Plugin where

getInt :: Int
getInt = 33
1个回答

14
问题在于您正在使用 IIModule。这表明您想将模块及其中的所有内容,包括未导出的内容导入上下文中。这与 GHCi 中带有星号的 :load 命令基本相同。正如您已经注意到的那样,这只适用于解释代码,因为它允许您“查看”模块内部。
但这不是您在这里所需要的。您需要的是将其加载为使用 :moduleimport 声明一样,与编译的模块一起使用。为此,您可以使用 IIDecl,它接受一个导入声明,您可以使用 simpleImportDecl 创建它:
setContext [IIDecl $ simpleImportDecl (mkModuleName "Plugin")]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接