python - 静态链接 Python,但仍支持外部 .pyd 模块

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

我正在考虑将 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 导出所有公共(public) 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 中的“导入套接字”将导致发生 LoadLibrary("socket.pyd")。这将隐式加载我的自定义 python35.dll。尝试加载 python35.dll 时发生故障,无法找到其转发的入口点。这似乎是因为 myapp.exe 不会成为库搜索路径的一部分。我似乎可以通过将 myapp.exe 复制到 myapp.dll 来验证这一点。如果我这样做,那么 python35.dll 加载工作,但这不是解决方案,因为这将导致 Python 环境的 2 个拷贝(一个在 myapp.exe 中,一个在 myapp.dll 中)

我也研究过其他可能的途径,但还没有找到合适的解决方案:

  • 以某种方式让 .exe 文件成为库搜索路径的一部分

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

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

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

总而言之,有没有一种方法可以将对 .dll 的调用重定向/转发到从 .exe 导出的函数/数据。谢谢!

最佳答案

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

关于python - 静态链接 Python,但仍支持外部 .pyd 模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41127960/

相关文章:

python - 如何防止模块级日志记录功能破坏我的记录器?

c++ - 无法创建DLL : Getting DLL "is not a valid Win32 application"

c - 检测 NUL 文件描述符(isatty 是假的)

windows - Windows卸载软件时如何找到安装位置

c++ - 将静态二维数组定义为私有(private)

windows - Perl 串口访问 [Windows 10]

python - 安装pycurl时出现"Could not run curl-config: [Errno 2] No such file or directory"

python - 如何在 django 项目中导入自定义的 settings.py 变量?

python - 如何找到可从包中导入的模块?

c++ - C++ 中原子更新最有效的 CAS 实现是什么?