Импортирование известной функции из уже скомпилированного двоичного файла с использованием API или подсказки GHC - PullRequest
5 голосов
/ 02 апреля 2011

У меня есть модуль Target, с функцией Target.accessMe внутри. Я каким-то образом компилирую этот модуль, а затем избавляюсь от исходного кода.

Теперь, какую серию тайных заклинаний я должен сделать для динамического импорта другой программы Target.accessMe? Эта программа заранее знает тип accessMe. Также учтите тот факт, что исходный код Target недоступен.

Пакет plugins справляется с этой задачей, но, похоже, имеет серьезные проблемы с работой в Windows. Я проверил источник plugins, но мне трудно его понять.

Я пытался использовать Hint, но могу узнать только, как оценить код, для которого у меня есть источник.

Спасибо за любую помощь!

Ответы [ 2 ]

2 голосов
/ 12 апреля 2011

Ответ на этот вопрос был дан мне в другом месте.GHC API способен сделать это.Вот две функции, одна из которых компилирует Target.hs, а другая обращается к Target.accessMe (и больше не требует наличия там исходного кода модуля Target).

import GHC
import DynFlags

compile :: String -> IO SuccessFlag
compile name = defaultRunGhc $ do
  dynflags <- getSessionDynFlags
  let dynflags' = dynflags -- You can change various options here.
  setSessionDynFlags dynflags'

  -- (name) can be "Target.hs", "Target", etc.
  target <- guessTarget name Nothing
  addTarget target
  load LoadAllTargets -- Runs something like "ghc --make".

Это функция, которая компилирует данный модуль и возвращает, была ли успешной компиляция или нет.Он использует вспомогательную функцию defaultRunGhc, которая определена как:

import GHC.Paths (libdir)

defaultRunGhc :: Ghc a -> IO a
defaultRunGhc = defaultErrorHandler defaultDynFlags . runGhc (Just libdir)

А теперь функция для извлечения значения из скомпилированного модуля.Исходный код модуля не обязательно должен присутствовать на этом этапе.

import Unsafe.Coerce (unsafeCoerce)

fetch :: String -> String -> IO Int -- Assumes we are fetching an Int value.
fetch name value = defaultRunGhc $ do
  -- Again, you can change various options in dynflags here, as above.
  dynflags <- getSessionDynFlags
  let m = mkModule (thisPackage dynflags) (mkModuleName name)
  setContext [] [(m, Nothing)] -- Use setContext [] [m] for GHC<7.

  fetched <- compileExpr (name ++ "." ++ value) -- Fetching "Target.accessMe".
  return (unsafeCoerce fetched :: Int)

И все!

0 голосов
/ 02 апреля 2011

Пакет plugins проблематичен в любом случае. Возможно, вы захотите взглянуть на подсказку .

...