使用 GHC 的 API 或提示从已编译的二进制文件导入已知函数

发布于 2024-10-30 11:19:50 字数 404 浏览 0 评论 0原文

我有一个模块 Target,其中有一个函数 Target.accessMe 。我以某种方式编译这个模块,然后删除源代码。

现在,我必须执行哪一系列神秘咒语才能使不同的程序动态导入 Target.accessMe?该程序预先知道accessMe的类型。另外,请考虑 Target 的源代码不可用这一事实。

plugins 包设法实现了这一点,但在 Windows 上工作似乎存在严重问题。我已经检查了 plugins 的源代码,但无法理解它。

我尝试过使用 Hint,但只能找出如何评估我拥有源代码的代码。

感谢您的帮助!

I have a module Target, with a function Target.accessMe inside it. I compile this module in some way, then get rid of the source code.

Now, what series of arcane incantations must I do to make a different program dynamically import Target.accessMe? This program knows accessMe's type in advance. Also, consider the fact that the source code of Target is not available.

The plugins package manages to accomplish this, but seems to have serious issues with working on Windows. I've checked out plugins's source, but am having trouble understanding it.

I've tried using Hint, but can only find out how to evaluate code that I have the source for.

Thanks for any help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

谎言月老 2024-11-06 11:19:50

这个问题的答案已经在其他地方给过我。 GHC API 能够做到这一点。这里有两个函数,其中一个编译 Target.hs,另一个访问 Target.accessMe(并且不需要 Target< 的源代码) /code> 模块不再存在)。

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)

就是这样!

The answer to this question has been given to me elsewhere. The GHC API is capable of doing this. Here are two functions, one of which compiles Target.hs, while the other accesses Target.accessMe (and doesn't require the source code of the Target module to be there anymore).

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".

That's a function that compiles a given module and returns whether compilation succeeded or not. It uses a defaultRunGhc helper function that is defined as:

import GHC.Paths (libdir)

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

And now a function for fetching a value from the compiled module. The module's source code need not be present at this point.

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)

And that's it!

对你而言 2024-11-06 11:19:50

无论如何,plugins 包是有问题的。您可能想查看提示

The plugins package is problematic anyway. You might want to look at Hint instead.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文