5

モジュールがあり、その中にTarget関数Target.accessMeがあります。このモジュールをなんらかの方法でコンパイルしてから、ソースコードを削除します。

さて、別のプログラムを動的にインポートするには、どのような一連の難解な呪文を実行する必要がありTarget.accessMeますか?accessMeこのプログラムは、のタイプを事前に知っています。また、のソースコードがTarget利用できないことも考慮してください。

pluginsパッケージはこれを達成することができますが、Windowsでの作業に深刻な問題があるようです。のソースを確認しましたpluginsが、理解できません。

を使用してみましHintたが、ソースがあるコードを評価する方法しかわかりません。

助けてくれてありがとう!

4

2 に答える 2

2

この質問に対する答えは、他の場所で私に与えられました。GHC API はこれを行うことができます。ここに 2 つの関数があります。1 つはコンパイルしTarget.hs、もう 1 つはアクセスします (モジュール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)

以上です!

于 2011-04-12T06:43:08.577 に答える
0

パッケージはpluginsとにかく問題があります。代わりにヒントを確認することをお勧めします。

于 2011-04-02T04:24:13.527 に答える