尝试通过 Process Pipe 发送/接收到 python 包装器,C++ 代码
Posted
技术标签:
【中文标题】尝试通过 Process Pipe 发送/接收到 python 包装器,C++ 代码【英文标题】:Attempting to send/receive over Process Pipe to python wrapper, c++ code 【发布时间】:2020-05-09 00:42:00 【问题描述】:我有一个包含一些 c++ 代码的 python 包装器。它是一个函数,我从我的 python 代码中设置为一个进程。它是一个 while 语句,我需要设置它何时应该关闭的条件。
对于这种情况,while 语句很简单。
while(TERMINATE == 0)
我有正在从 while 循环中发回的数据。我正在使用 pipe() 创建“输入”和“输出”对象。创建进程时,我将“输出”对象发送给函数。
fxn = self.FG.do_videosequence
(self.inPipe, self.outPipe) = Pipe()
self.stream = Process(target=fxn, args=(self.outPipe,))
self.stream.start()
正如我所提到的,在包装器中,我可以将数据发送回 python 脚本
PyObject *send = Py_BuildValue("s", "send_bytes");
PyObject_CallMethodObjArgs(pipe, send, temp, NULL);
这很好用。但是,我在向包装器中的 C++ 代码发送消息时遇到问题,告诉循环停止。
我想我会做的只是检查 poll(),因为这就是我在 python 脚本方面所做的。我想保持简单。当系统看到有来自 python 脚本的传入信号时,它会设置 TERMINATE = 1。所以我写了这个。
PyObject *poll = Py_BuildValue("p", "poll");
正如我期待 python 函数 poll() 的真假。我认为“p”是理想的,因为它会将 true 转换为 1,将 false 转换为 0。
在我的循环中
if(PyObject_CallMethodObjArgs(pipe, poll, NULL, NULL))
TERMINATE = 1;
我想使用 poll() 作为它的非阻塞,就像 recv() 一样。这样我就可以继续我的其他工作,并且每个周期检查一次 poll()。
但是,当我从 python 脚本发送信号时,它永远不会跳闸。
self.inPipe.send("Hello");
我不确定断开连接在哪里。当我打印 poll() 请求时,我一直得到 0 。我要么没有正确调用它,它只是默认为 0。或者我实际上并没有生成一个信号来触发 poll() 调用。因此它始终为 0。
有没有人知道我做错了什么?
*****更新******
我发现了一些其他信息。
PyObject *poll = Py_BuildValue("p", "poll");
应该是
PyObject *poll = Py_BuildValue("s", "poll");
当我传递一个字符串作为对调用它的函数的引用时,应该将其引用为字符串。它与返回类型无关。
从那里返回
PyObject_CallMethodObjArgs(pipe, poll, NULL, NULL)
是一个 pyobject,因此需要根据 pyobject 检查它。比如打电话给
PyObject_IsTrue
判断它的真假。我将对我的代码进行更改,如果我有解决方案,我会用答案更新帖子。
【问题讨论】:
我对你的代码感到困惑。您确实意识到您需要两个管道……即四个文件描述符……来处理双向通信。正确的?调用 pipe()(系统调用)返回的描述符对包括管道的两端;一个由父进程使用,另一个由子进程使用。两次调用管道,父级各保持一种类型,子级使用每个类型的相应相对端,为您提供双向管道对。还要确保您的 I/O 至少在每一端都是非阻塞的!否则很可能出现死锁。 @JimDennis 嗨,谢谢。我已经更新了我的帖子以反映您的想法。我还发布了一些我能够找到的新信息。 @JimDennis Jim,也许你可以澄清一下。我刚刚检查了 python 文档,它说 pipe() 函数默认为两种方式,双工。它给出的示例似乎表明不需要四个描述符。 docs.python.org/3.4/library/… 注意:我特别提到了 Unix/Linux 系统调用 pipe() ...但 Python os.pipe() 具有相似的语义:docs.python.org/3/library/os.html?highlight=os.pipe#os.pipe。我不知道你在读什么文档。 (它们是针对 C 级 Python API 的吗?)但也许这个讨论对您有用:claytonrichey.com/post/c-cpp-python-pipe 我的部分困惑是我几乎从未使用过 Python 的 C API; 【参考方案1】:所以我已经找到了解决方案。最后我犯了两个错误。 第一个错误是当我创建对我正在调用的 python 函数的 pyobject 引用时。我弄错了信息,在阅读上下文之前插入了一个“p”的想法。所以
PyObject *poll = Py_BuildValue("p", "poll");
应该是
PyObject *poll = Py_BuildValue("s", "poll");
第二个错误是我如何处理
的返回值PyObject_CallMethodObjArgs(pipe, poll, NULL, NULL)
虽然它调用了一个python对象是真的,但它不是返回一个简单的真假值,而是一个python对象。所以我特别需要处理python对象,通过调用
PyObject_IsTrue(Pyobject o)
以 poll() 请求的返回作为参数。我现在能够从包装器中包含的 python 脚本和 C api 发送/接收。
【讨论】:
以上是关于尝试通过 Process Pipe 发送/接收到 python 包装器,C++ 代码的主要内容,如果未能解决你的问题,请参考以下文章