मैंने हास्केल में प्लगइन के बारे में पढ़ा है लेकिन मुझे अपने उद्देश्यों (आदर्श रूप से उत्पादन वातावरण में उपयोग करने के लिए) का संतोषजनक तरीका नहीं मिल सकता है।बॉक्स से बाहर हास्केल प्लगइन सिस्टम
मेरे प्लगइन प्रणाली लक्ष्य हैं:
- उत्पादन वातावरण बॉक्स (सभी precompiled) से बाहर होने के लिए आवश्यक है। प्लगइन लोड करने के लिए
- सक्षम रीसेट ऐप/सेवा सक्षम है लेकिन आदर्श रूप से यह फ्लाई पर प्लगइन लोड और अपडेट करेगा।
एक न्यूनतम उदाहरण हो सकता है:
एप्लिकेशन/सेवा ~ प्लगइन्स इंटरफ़ेस
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
}
Plugin1 का उपयोग कर। hs
module Plugin1 (
getPlugin
) where
import SharedTypes
getPlugin :: PluginInterface
getPlugin = PluginInterface "Plugin1" $ \x -> 1 * x
Plugin2.hs
module Plugin2 (
getPlugin
) where
import SharedTypes
getPlugin :: PluginInterface
getPlugin = PluginInterface "Plugin2" $ \x -> 2 * x
अनुप्रयोग।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)
संकलन और निष्पादन
[[email protected] 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)
[[email protected] PluginSystem]$ ghc --make -dynamic -fPIC -O3 Plugin2.hs
[2 of 2] Compiling Plugin2 (Plugin2.hs, Plugin2.o)
[[email protected] PluginSystem]$ mv Plugin1.o plugins/Plugin1.plugin
[[email protected] PluginSystem]$ mv Plugin2.o plugins/Plugin2.plugin
[[email protected] PluginSystem]$ ghc --make -dynamic -fPIC -O3 app.hs
[2 of 2] Compiling Main (app.hs, app.o)
Linking app ...
[[email protected] PluginSystem]$ ./app
Plugin name: Plugin1
Run := 34
Plugin name: Plugin2
Run := 68
धन्यवाद! मुझे लगता है कि सही है! * "हालांकि" * हां, संगतता सुनिश्चित करने के लिए कई अतिरिक्त चीजें किए जा सकते हैं ('getVersion') और retrocompatibility (' getPlugin :: शायद (ए -> ए) ', getpluginV2 :: शायद (ए -> ए - > ए) ', और इसी तरह)। – josejuan