gpt4 book ai didi

haskell - 开箱即用的 Haskell 插件系统

转载 作者:行者123 更新时间:2023-12-03 15:06:20 25 4
gpt4 key购买 nike

我已经阅读了 Haskell 中的插件,但我无法找到一种令人满意的方式来实现我的目的(最好在生产环境中使用)。
我的插件系统目标是:

  • 生产环境必须开箱即用(全部预编译)。
  • 加载插件已启用重置应用程序/服务,但理想情况下它会即时加载和更新插件。

  • 一个最小的例子可能是:
    应用/服务~插件接口(interface)
    module SharedTypes (PluginInterface (..)) where

    data PluginInterface =
    PluginInterface { pluginName :: String
    , runPlugin :: Int -> Int }
    一些插件列表
    -- ~/plugins/plugin{Nth}.??   (with N=1..)
    module Plugin{Nth}( getPlugin ) where

    import SharedTypes

    getPlugin :: PluginInterface
    getPlugin = PluginInterface "{Nth}th plugin" $ \x -> {Nth} * x
    应用/服务
    ...
    loadPlugins :: FilePath -> IO [PluginInterface]
    loadPlugins = undefined
    ...
    我认为使用动态编译链接库(将每个 Plugin{Nth} 编译为共享库)可以工作(作为 FFI)但是
  • 如何在运行时枚举和加载每个共享库? (获取每个 getPlugin 功能点)
  • 有更好的办法吗? (例如,运行应用程序/服务之前的一些“魔术”进程)

  • 谢谢!
    更新
    完整运行示例
    遵循出色的@xnyhps 答案,使用 ghc 7.10 的完整运行示例
    SharedTypes.hs
    module SharedTypes (
    PluginInterface (..)
    ) where

    data PluginInterface =
    PluginInterface { pluginName :: String
    , runPlugin :: Int -> Int
    }
    插件1.hs
    module Plugin1 (
    getPlugin
    ) where

    import SharedTypes

    getPlugin :: PluginInterface
    getPlugin = PluginInterface "Plugin1" $ \x -> 1 * x
    插件2.hs
    module Plugin2 (
    getPlugin
    ) where

    import SharedTypes

    getPlugin :: PluginInterface
    getPlugin = PluginInterface "Plugin2" $ \x -> 2 * x
    app.hs
    import SharedTypes
    import System.Plugins.DynamicLoader
    import System.Directory
    import Data.Maybe
    import Control.Applicative
    import Data.List
    import System.FilePath
    import Control.Monad

    loadPlugins :: FilePath -> IO [PluginInterface]
    loadPlugins path = getDirectoryContents path >>= mapM loadPlugin . filter (".plugin" `isSuffixOf`)
    where loadPlugin file = do
    m <- loadModuleFromPath (combine path file) -- absolute path
    (Just path) -- base of qualified name (or you'll get not found)
    resolveFunctions
    getPlugin <- loadFunction m "getPlugin"
    return getPlugin

    main = do

    -- and others used by plugins
    addDLL "/usr/lib/ghc-7.10.1/base_I5BErHzyOm07EBNpKBEeUv/libHSbase-4.8.0.0-I5BErHzyOm07EBNpKBEeUv-ghc7.10.1.so"
    loadModuleFromPath "/srv/despierto/home/josejuan/Projects/Solveet/PluginSystem/SharedTypes.o" Nothing

    plugins <- loadPlugins "/srv/despierto/home/josejuan/Projects/Solveet/PluginSystem/plugins"

    forM_ plugins $ \plugin -> do
    putStrLn $ "Plugin name: " ++ pluginName plugin
    putStrLn $ " Run := " ++ show (runPlugin plugin 34)
    编译执行
    [josejuan@centella PluginSystem]$ ghc --make -dynamic -fPIC -O3 Plugin1.hs
    [1 of 2] Compiling SharedTypes ( SharedTypes.hs, SharedTypes.o )
    [2 of 2] Compiling Plugin1 ( Plugin1.hs, Plugin1.o )
    [josejuan@centella PluginSystem]$ ghc --make -dynamic -fPIC -O3 Plugin2.hs
    [2 of 2] Compiling Plugin2 ( Plugin2.hs, Plugin2.o )
    [josejuan@centella PluginSystem]$ mv Plugin1.o plugins/Plugin1.plugin
    [josejuan@centella PluginSystem]$ mv Plugin2.o plugins/Plugin2.plugin
    [josejuan@centella PluginSystem]$ ghc --make -dynamic -fPIC -O3 app.hs
    [2 of 2] Compiling Main ( app.hs, app.o )
    Linking app ...
    [josejuan@centella PluginSystem]$ ./app
    Plugin name: Plugin1
    Run := 34
    Plugin name: Plugin2
    Run := 68

    最佳答案

    the dynamic-loader package ,它允许您将额外的目标文件或共享库加载到您的进程中。 (Hackage 上的版本不适用于 7.10,但当前的 version on GitHub does 。)

    有了这个,你可以这样做:

    import System.Plugins.DynamicLoader
    import System.Directory

    loadPlugins :: FilePath -> IO [PluginInterface]
    loadPlugins path = do
    files <- getDirectoryContents path
    mapM (\plugin_path -> do
    m <- loadModuleFromPath (path ++ "/" ++ plugin_path) (Just path)
    resolveFunctions
    plugin <- loadFunction m "getPlugin"
    return plugin) files

    但是,您必须记住,整个过程是 非常不安全 : 如果你改变你的 PluginInterface数据类型并尝试加载使用旧版本编译的插件,您的应用程序将崩溃。您必须希望 getPlugin函数的类型为 PluginInterface ,没有检查。最后,如果插件来自不受信任的来源,它可以执行任何操作,即使您尝试调用的函数在 Haskel 中应该是纯函数。

    关于haskell - 开箱即用的 Haskell 插件系统,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30681954/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com