【问题标题】:How would a Python script running on Linux call a routine in a Python script running under Wine?在 Linux 上运行的 Python 脚本如何调用在 Wine 下运行的 Python 脚本中的例程?
【发布时间】:2016-05-01 06:30:46
【问题描述】:

我有一个在 Linux 上运行的 Python (3) 脚本,称为主脚本,它必须从专有 DLL 调用例程。到目前为止,我已经使用 Wine 使用以下结构解决了这个问题:

# Main script running on Linux
import subprocess
# [...]
subprocess.Popen('echo "python dll_call.py %s" | wine cmd &' % options, shell = True)
# [...]

脚本 dll_call.py 由安装在 Wine 下的 Windows Python (3) 解释器执行。它将返回值转储到一个文件中,然后由等待的主脚本拾取该文件。如果我必须连续执行几次,这并不完全可靠且速度非常慢。

我想启动脚本 dll_call.py 一次,提供某种类型的简单服务器,它应该以某种方式公开所需的例程。归根结底,我希望主脚本看起来像这样:

# Main script running on Linux
import subprocess
# [...]
subprocess.Popen('echo "python dll_call_server.py" | wine cmd &', shell = True)
# [...]
return_values = call_into_dll(options)

如何才能最好地实现这一点(如果需要速度并且不关心安全性)?


感谢@jsbueno 和@AustinHastings 的回答和建议。

对于那些有类似问题的人:受上述答案的启发,我编写了一个小型 Python 模块,用于在 Linux 上从 Python 调用 Windows DLL。它基于常规 Linux/Unix Python 进程和基于 Wine 的 Python 进程之间的 IPC。因为我在太多不同的用例/场景中都需要它,所以我将它设计为“通用”ctypes module 替代品,它会在后台自动完成大部分所需的管道。

示例:假设您在 Linux 上使用 Python,安装了 Wine,并且您想调用 msvcrt.dll(Microsoft C 运行时库)。您可以执行以下操作:

import zugbruecke as ctypes
dll_pow = ctypes.cdll.msvcrt.pow
dll_pow.argtypes = (ctypes.c_double, ctypes.c_double)
dll_pow.restype = ctypes.c_double
print('You should expect "1024.0" to show up here: "%.1f".' % dll_pow(2.0, 10.0))

Source code (LGPL)PyPI packagedocumentation。它的边缘仍然有点粗糙(即 alpha 和不安全),但它确实可以处理大多数类型的参数(包括指针)。

【问题讨论】:

    标签: python linux ipc wine multiplatform


    【解决方案1】:

    您可以使用 Python 的 stdlib 中内置的 XMLRPC 客户端和服务器来做您想做的事。只需让您的 Wine-Python 将所需的函数公开为 XMLRPC 方法,然后从任何其他 Python 程序对其进行进程间调用。

    它也适用于从 CPython 调用在 Jython 或 IronPython 中运行的函数,也适用于跨 Python2 和 Python3 - 模块文档中包含的示例本身就足够了。只需查看文档:https://docs.python.org/2/library/xmlrpclib.html

    如果您需要在客户端异步调用,或者服务器站点响应多个进程,您可以找到其他框架来构建调用 - Celery 还应该可以跨多个不同的 Python 工作,同时保留调用兼容性,而且在性能方面肯定足够了。

    【讨论】:

      【解决方案2】:

      您希望在两个进程之间进行通信,其中一个进程因受 WINE 引擎的控制而被遮挡。

      我在这里的第一个想法是使用一种非常解耦形式的 IPC。紧密耦合和涉及 WINE 之类的东西可能会出错的事情太多了。

      最后,对于刚接触这类东西的人来说,这怎么能变得容易?

      显而易见的答案是设置网络服务器。有很多教程使用 Python 中的大量包来响应 HTTP 请求并生成 HTTP 请求。

      因此,在您的 WINE 进程中设置一个小的 HTTP 响应程序,侦听一些非标准端口(不是 8080 或 80),并将请求转换为对您的 DLL 的调用。如果你够聪明,你会将网络请求 (http://localhost:108000/functionname?arg1=foo&arg2=bar) 解释为可能不同的 DLL 调用。

      另一方面,在您的非 WINE 代码中创建一个 HTTP 客户端并向您的服务器发出请求。

      【讨论】:

      • 所以,正如我在回答中列出 XMLRPC 一样:Python 自己的内置 XMLRPC 服务器通过 http 工作并完全满足您需要的所有要求,此外还有调用 - 包括参数和值序列化 -一切设置好后,在客户端和服务器端都是透明的。
      猜你喜欢
      • 2022-08-06
      • 1970-01-01
      • 2018-05-20
      • 1970-01-01
      • 2023-03-21
      • 2019-03-15
      • 2020-12-11
      • 1970-01-01
      • 2015-02-18
      相关资源
      最近更新 更多