我正在编写一个我想要模块化架构的工具。我的意思是,用户可以在启动时写下要加载的模块列表,而我的工具将为我加载相应的.o
。
这是到目前为止我设法编写的代码:
module Core where
import Data.Monoid ((<>))
import Data.Text (pack, unpack)
import System.Directory (getHomeDirectory)
import System.Plugins.DynamicLoader
loadPlugins :: [Text] -> IO ()
loadPlugins plugins = do
home <- getHomeDirectory
-- addDLL "/home/tchoutri/.stack/programs/x86_64-linux/ghc-tinfo6-8.4.3/lib/ghc-8.4.3/base-4.11.1.0/libHSbase-4.11.1.0-ghc8.4.3.so"
let paths = fmap (\x -> (pack home) <> "/.local/lib/polynot/polynot-" <> x <> ".o") plugins
forM_ paths $ \path -> load path
where
load path = do
m <- loadModuleFromPath (unpack path) (Just $ unpack path)
resolveFunctions
loadFunction m "runPlugin"
此刻我要加载的插件非常简单:
{-# LANGUAGE OverloadedStrings #-}
module Polynot.Plugin.Twitter where
runPlugin :: IO ()
runPlugin = putStrLn "[Twitter] 'sup"
它是用stack ghc -- --make -dynamic -fPIC -O3 twitter.hs
编译的。然后在polynot-twitter.o
中将其重命名为~/.local/lib/polynot/
。
编译顺利,当我运行stack exec -- polynot
时,出现此错误:
polynot: user error (Unable to get qualified name from: /home/tchoutri/.local/lib/polynot/polynot-twitter.o)
谷歌快速搜索显示,此错误的唯一实例出现在源代码中。 :/
此外,我使用的是git版本的dynamic-loader。
(我可能会误以为我选择了模块化体系结构,我完全接受。如果您有更好的方法可以使用,则可以对此发表评论:)
答案 0 :(得分:1)
我无法复制您的错误。我得到一个Prelude.head: empty list
异常。
但是,我的猜测是它与dynamic-loader
中的功能有关,期望从匹配模块层次结构的层次目录结构中加载模块。
简而言之,如果我将插件存储在:
~/.local/lib/polynot/Polynot/Plugin/Twitter.o
并像这样使用loadModule
:
loadModule "Polynot.Plugin.Twitter"
(Just "/home/buhr/.local/lib/polynot") (Just "o")
那对我来说还可以。
我使用的Main.hs
是以下内容:
{-# LANGUAGE OverloadedStrings #-}
import Control.Monad (forM_)
import Data.Monoid ((<>))
import Data.Text (pack, unpack, Text)
import System.Directory (getHomeDirectory)
import System.Plugins.DynamicLoader
loadPlugins :: [Text] -> IO ()
loadPlugins plugins = do
home <- getHomeDirectory
let basedir = (pack home) <> "/.local/lib/polynot"
forM_ plugins (load basedir)
where
load dir plugin = do
m <- loadModule (unpack plugin) (Just $ unpack dir) (Just "o")
resolveFunctions
entry <- loadFunction m "runPlugin"
entry
main = do
putStrLn "starting!"
loadPlugins ["Polynot.Plugin.Twitter"]
putStrLn "done!"