【问题标题】:Statically linking Python, but still supporting external .pyd modules静态链接 Python,但仍支持外部 .pyd 模块
【发布时间】:2016-12-13 18:19:15
【问题描述】:

我正在研究将 Python 与我的应用程序进行静态链接。这样做的原因是因为在某些测试用例中我看到了 10% 的速度提升。我的应用程序大量使用 Python C-API,并且似乎 Whole Program Optimization 能够进行一些很好的优化。我希望 Profile Guided Optimizations 也会获得更多收益。这一切都在 MSVC2015 中完成

到目前为止,我已将 pythoncore 项目 (python35.dll) 重新编译为一个静态库,并将其与我的应用程序链接起来(我们称之为 myapp.exe)。仅供参考,除了将项目类型更改为静态之外,唯一需要做的另一件事是在静态库编译期间和编译 myapp.exe 时设置定义 Py_NO_ENABLE_SHARED。这很好用,这就是我能够获得 10% 速度提升测试结果的方法。

所以下一步是继续支持具有 .pyd 文件(即重命名为 .pyd 的 .dll 文件)的外部 python 模块。这些模块将被编译并期望与 python35.dll 动态链接,因此我需要为该要求提供一种解决方法,因为所有 python 函数现在都嵌入到 myapp.exe 中。

首先,我使用 .def 文件从 myapp.exe 导出所有公共 Python 函数。这很好用。

缺少的部分是如何创建一个 python35.dll,它将所有调用重定向到从 myapp.exe 导出的函数。

我的第一次尝试是使用 DLL 转发。我制作了一个自定义的 python35.dll,它有一个 .def 文件,其中包含以下行:

PyArg_Parse=myapp.PyArg_Parse

理论上,这是可行的。如果我在 socket.pyd 上使用 Dependency Walker,它会正确打开我的 python35.dll 并显示所有调用都被转发到 myapp.exe。

但是,当实际运行 myapp.exe 并尝试导入套接字时,它无法从 myapp.exe 加载所需的入口点。 Python 中的 'import socket' 将导致 LoadLibrary("socket.pyd") 发生。这将隐式加载我的自定义 python35.dll。尝试加载 python35.dll 时发生故障,无法找到其转发的入口点。这似乎是因为 myapp.exe 不会成为库搜索路径的一部分。我似乎可以通过将 myapp.exe 复制到 myapp.dll 来验证这一点。如果我这样做,那么 python35.dll 加载工作,但这不是一个解决方案,因为这将导致 Python 环境的 2 个副本(一个在 myapp.exe 中,一个在 myapp.dll 中)

我也研究过但没有找到正确解决方案的其他可能途径:

  • 不知何故让 .exe 文件成为库搜索路径的一部分

  • 使用 Windows 清单/配置以某种方式重定向库

  • 手动使用 declspec(naked) 和 jmp 语句更明确地包装 .dll。我在 x64 中工作,所以我认为这不可能了?

  • 我可以手动完成整个 Python API 并手动包装每个函数。如果我能找到一种方法来创建所有导出的函数定义,这是可行的,所以这不是大量的手动工作。

总之,有没有办法将对 .dll 的调用重定向/转发到从 .exe 导出的函数/数据。谢谢!

【问题讨论】:

  • 你不能创建一个不同的myapp.exe (也)使用python35.dll 来实现其大部分功能(基本上是旧的重命名myapp.exe)吗?
  • 有趣,您是说将所有 python 和 myapp 的所有功能合并到 python35.dll 中,对吗?是的,这似乎可行......谢谢你的想法!不过,我想知道是否有更正式的方式来做到这一点......
  • 是的,这是我对解决方法的建议。至于“正式”方式,也许有一种方法可以制作一个更加“静态”的 Python 解释器版本,其中所有内置模块都静态链接到其中,然后也许你可以构建和利用它(假设它仍然能够动态导入/加载其他非链接模块)。

标签: python c++ windows visual-c++ dll


【解决方案1】:

我最终采用了 @martineau 在 cmets 中建议的解决方案,即将我的所有应用程序(包括 Python)放入单个 .dll 而不是 .exe 中。那么 .exe 只是一个调用 .dll 的简单文件,没有其他任何作用。

【讨论】:

    猜你喜欢
    • 2014-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-03
    • 2010-09-06
    • 2021-04-18
    相关资源
    最近更新 更多