Close

29.06.2015

я хаскель забросил, но МАГИЮ ПОКАЖУ.

Динамику на хаскеле видели когда нибудь, как вам динамика ?  Фуу??

да ладно!, куда без нее.  интересует:?

  • динамически подгружаемые плагины !
  • вызов функций из них !
  • вообще динамическая интерпретация хаскель кода в готовой хаскель программе !

вот такое я вытворял как-то, а тут нашел свои эксперименты и решил поделится, редкость же дикая — прошу под кат! налетай.

подгрузка объектника на ходу

сделаем простой плагин который будет что-то экспортировать, ну хоть функцию 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 который мы используем, серезная весома штуковина… но она того стоит (наверное)

так просто это не собрать нужно доустанавливать… но проблема в том, что

GHC package is hidden 

разруливаем

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))

но тут я не уверен что быстро… вообще не уверен, а в случае со сборкой — скорость будет на высоте. быстрее Сей — как часто у хаскеля и бывает.

 

2 Comments on “я хаскель забросил, но МАГИЮ ПОКАЖУ.

Михаил Павлов
30.06.2015 в 00:20
Михаил Павлов
30.06.2015 в 09:15

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *