я хаскель забросил, но МАГИЮ ПОКАЖУ.
Динамику на хаскеле видели когда нибудь, как вам динамика ? Фуу??
да ладно!, куда без нее. интересует:?
- динамически подгружаемые плагины !
- вызов функций из них !
- вообще динамическая интерпретация хаскель кода в готовой хаскель программе !
вот такое я вытворял как-то, а тут нашел свои эксперименты и решил поделится, редкость же дикая — прошу под кат! налетай.
подгрузка объектника на ходу
сделаем простой плагин который будет что-то экспортировать, ну хоть функцию main хотя бы
надо это собрать
$ ghc Plug.hs [1 of 1] Compiling Plug ( Plug.hs, Plug.o )
получили *.o объектный файл — ЕГО и будем грузить, да да — прямо объектник.
дальше пишем прогу которая будет его тянуть
что тут у нас ?
самое главное надо поставить некий Plugins https://hackage.haskell.org/package/plugins
ставим
$ cabal install happy # нужен, без него plagins не встанет # там happy ... поправьте по своему путь export PATH=/home/pavlov/.cabal/bin/:$PATH # дальше я все приведу с выводом, для души $ cabal install plugins Resolving dependencies... Configuring haskell-src-1.0.2.0... Building haskell-src-1.0.2.0... Preprocessing library haskell-src-1.0.2.0... [1 of 6] Compiling Language.Haskell.Syntax ( Language/Haskell/Syntax.hs, dist/build/Language/Haskell/Syntax.o ) [2 of 6] Compiling Language.Haskell.Pretty ( Language/Haskell/Pretty.hs, dist/build/Language/Haskell/Pretty.o ) [3 of 6] Compiling Language.Haskell.ParseMonad ( Language/Haskell/ParseMonad.hs, dist/build/Language/Haskell/ParseMonad.o ) [4 of 6] Compiling Language.Haskell.ParseUtils ( Language/Haskell/ParseUtils.hs, dist/build/Language/Haskell/ParseUtils.o ) [5 of 6] Compiling Language.Haskell.Lexer ( Language/Haskell/Lexer.hs, dist/build/Language/Haskell/Lexer.o ) [6 of 6] Compiling Language.Haskell.Parser ( dist/build/Language/Haskell/Parser.hs, dist/build/Language/Haskell/Parser.o ) In-place registering haskell-src-1.0.2.0... Installing library in /home/pavlov/.cabal/lib/haskell-src-1.0.2.0/ghc-7.6.3 Registering haskell-src-1.0.2.0... Installed haskell-src-1.0.2.0 Downloading plugins-1.5.4.0... Configuring plugins-1.5.4.0... configure: WARNING: unrecognized options: --with-compiler, --with-gcc checking build system type... i686-pc-linux-gnu checking for ghc... ghc checking for value of __GLASGOW_HASKELL__... 706 checking for ghc library directory... /usr/lib/ghc checking for gcc... gcc checking whether the C compiler works... yes checking for C compiler default output file name... a.out checking for suffix of executables... checking whether we are cross compiling... no checking for suffix of object files... o checking whether we are using the GNU C compiler... yes checking whether gcc accepts -g... yes checking for gcc option to accept ISO C89... none needed checking for arc4random... no checking for a BSD-compatible install... /usr/bin/install -c configure: creating ./config.status config.status: creating config.mk config.status: creating testsuite/makewith/io/TestIO.conf config.status: creating testsuite/makewith/unsafeio/Unsafe.conf config.status: creating config.h configure: WARNING: unrecognized options: --with-compiler, --with-gcc Building plugins-1.5.4.0... Preprocessing library plugins-1.5.4.0... [ 1 of 12] Compiling System.Plugins.Process ( src/System/Plugins/Process.hs, dist/build/System/Plugins/Process.o ) [ 2 of 12] Compiling System.Plugins.Parser ( src/System/Plugins/Parser.hs, dist/build/System/Plugins/Parser.o ) [ 3 of 12] Compiling System.Plugins.LoadTypes ( src/System/Plugins/LoadTypes.hs, dist/build/System/Plugins/LoadTypes.o ) [ 4 of 12] Compiling System.Plugins.Consts ( src/System/Plugins/Consts.hs, dist/build/System/Plugins/Consts.o ) [ 5 of 12] Compiling System.Plugins.Env ( src/System/Plugins/Env.hs, dist/build/System/Plugins/Env.o ) [ 6 of 12] Compiling System.Plugins.Utils ( src/System/Plugins/Utils.hs, dist/build/System/Plugins/Utils.o ) src/System/Plugins/Utils.hs:69:1: Warning: Module `Prelude' does not export `catch' [ 7 of 12] Compiling System.Plugins.Make ( src/System/Plugins/Make.hs, dist/build/System/Plugins/Make.o ) [ 8 of 12] Compiling System.Plugins.Load ( src/System/Plugins/Load.hs, dist/build/System/Plugins/Load.o ) [ 9 of 12] Compiling System.Plugins ( src/System/Plugins.hs, dist/build/System/Plugins.o ) [10 of 12] Compiling System.Eval.Utils ( src/System/Eval/Utils.hs, dist/build/System/Eval/Utils.o ) [11 of 12] Compiling System.Eval.Haskell ( src/System/Eval/Haskell.hs, dist/build/System/Eval/Haskell.o ) [12 of 12] Compiling System.Eval ( src/System/Eval.hs, dist/build/System/Eval.o ) In-place registering plugins-1.5.4.0... Installing library in /home/pavlov/.cabal/lib/plugins-1.5.4.0/ghc-7.6.3 Registering plugins-1.5.4.0... Installed plugins-1.5.4.0
затем собираем прогу
$ ghc proga1.hs [1 of 1] Compiling Main ( proga1.hs, proga1.o ) Linking proga1 ...
запускаем и видим чудо…
$ ./proga1 Loading thing Loaded success 1234000 Loading main Loaded hello world from plugin
что тут произошло ? МЫ ПОДГРУЗИЛИ ВНЕШНИЙ ОБЪЕКТНИК, который можно по жизни подменять… и выполнили код из него, УЖЕ ПОХОЖЕ НА ДИНАМИКУ, не правда ли ?
шаг 2. передадим туда аргументы + немного IO
наш плагин немного изменим
добавили ввод вывод строки и у функции main теперь есть аргумент
сделаем «вызыватель»
соберем и запустим
pavlov@pavlov-pc:~/workspace/lua/ghc-dynamic/dynload$ ghc s5.hs [1 of 1] Compiling Main ( s5.hs, s5.o ) Linking s5 ... pavlov@pavlov-pc:~/workspace/lua/ghc-dynamic/dynload$ ./s5 Loading Loaded success 1234000 asxas hello from plugin arg=arg---value line=asxas
asxas — введено с клавы, и параметр напечатался, — все как надо.
шаг 3 — динамическая сборка модулей
соберем прямо из своей проги простенький модуль, вот он:
теперь код который собирает
тут новое это GHC который мы используем, серезная весома штуковина… но она того стоит (наверное)
так просто это не собрать нужно доустанавливать… но проблема в том, что
разруливаем
sudo ghc-pkg expose ghc
у меня ничего не конфликтануло — мне повезло, вы уж сами если что трабшотьте
собирать надо так:
ghc -package ghc simple.hs
если у вас не соберется значит в версии GHC чего-то испортилось со времен моих экспериментов, я нашел в сети поправки и более «новый» способ сделать это будет таким
попробуйте его собрать, тут немного типы иные приходят в обработчик…
запускаем:
pavlov@pavlov-pc:~/workspace/lua/ghc-dynamic$ ghc -package ghc simple.hs [1 of 1] Compiling Main ( simple.hs, simple.o ) Linking simple ... pavlov@pavlov-pc:~/workspace/lua/ghc-dynamic$ ./simple pavlov@pavlov-pc:~/workspace/lua/ghc-dynamic$ ll B.o -rw-rw-r-- 1 pavlov pavlov 2092 июня 29 23:47 B.o
видите — плагин собрался «как бы сам»
тупо EVAL , не интересно, но если надо…
делаем такое
и оно работает
pavlov@pavlov-pc:~/workspace/lua/ghc-dynamic$ ghc s2.hs [1 of 1] Compiling Main ( s2.hs, s2.o ) Linking s2 ... pavlov@pavlov-pc:~/workspace/lua/ghc-dynamic$ ./s2 Right (Just (Just 7))
но тут я не уверен что быстро… вообще не уверен, а в случае со сборкой — скорость будет на высоте. быстрее Сей — как часто у хаскеля и бывает.
Михаил Павлов
30.06.2015 в 00:20каменты в G+
https://plus.google.com/111565911903845389442/posts/FVacfEjiYgZ
Михаил Павлов
30.06.2015 в 09:15G+ в сообществе ruHaskell https://plus.google.com/u/0/111565911903845389442/posts/gGyP44ZbyVj?cfem=1