C++与Python之间的简单IPC(跨平台)

46

我有一个在后台运行的C++进程,会不时生成一些“事件”,需要由同一台机器上运行的Python进程来处理。

  • C++端的代码应尽可能轻量级。
  • Python端只需读取数据,不需要写入。
  • 实现必须是跨平台的。
  • 发送的数据非常简单。

我的选择有哪些?

谢谢


1
你的程序运行在哪个操作系统下?基于管道的IPC在类Unix机器上非常容易实现。 - Alexandre C.
“the C side” 是一个打字错误,对吧? - Gabriel Devillers
7个回答

59

zeromq -- 没有其他东西。将消息作为字符串进行编码。

但是,如果您想使用库来获取序列化,则可以使用protobuf。它将为Python和C++生成类。您可以在两端使用SerializeToString()和ParseFromString()函数,然后通过ZeroMq传输字符串。

问题解决了,我怀疑没有其他解决方案会更快,并且也没有其他解决方案会如此易于布线和简单易懂。

如果要使用特定的系统原语进行rpc,例如Windows上的命名管道和unix上的Unix域套接字,则应查看Boost::ASIO。但是,除非您具有网络背景并且对C++有非常好的理解,否则这将非常耗费时间。


5
多选项加1。并指出protobuf仅是序列化方案的解决方案。 - André Caron
3
我选择使用ZeroMQ是因为服务器端的实现只有12行代码!!如果不需要依赖库,我是不喜欢使用它们的,但ZeroMQ是个例外。 :) - Lee Treveil
是的,zeromq 正是为您的用例而设计的。它非常原始且易于理解。尽管它很原始,但其鲁棒性很强,因为您可以在其上实现更复杂的消息构造。在我的工作中,我选择在 boost:ASIO 之上实现自己的 RPC 系统,因为我需要上面提到的系统基元。 - Hassan Syed
Zeromq是最糟糕的。我已经用ZeroMQ做了这件事,现在要转向其他任何东西。ZeroMQ根本没有失败的概念。如果您尝试发送消息并且您的进程崩溃了,那么就无法告诉。它将继续永远尝试发送。还有许多其他问题,其中失败完全不透明,因此重试也是不可能的。 - ghostbust555
@ghostbust555 自从我最后一次使用zeromq以来已经很长时间了。 “根本没有失败的概念”,换句话说,“发送并忘记”,这种消息传递方式并没有什么问题。如果需要,您还可以在zeromq的基础上构建故障机制。话虽如此,现在我可能更倾向于使用GRPC,但是如果我没记错的话,它确实有相当沉重的Python依赖性。 - Hassan Syed
@HassanSyed 你说得对,你可以在上面构建故障检测,但是必须做一些像中止线程以杀死无限等待队列之类的混乱事情。我从未发现不需要被通知消息传递失败的原因。如果您正在进行IPC并且消息发送失败,则几乎总是要通知某人或重新启动侦听器。我认为没有这种能力会大大降低任何通信库的实用性。 - ghostbust555

5

Google的protobuf是一个用于程序之间RPC的优秀库。它可以生成PythonC++的绑定。

如果您需要分布式消息系统,也可以使用RabbitMQzeromqActiveMQ等工具。有关消息队列库的讨论,请参见此问题


RabbitMq相比之下,ZeroMq就像是一只苍蝇拍,而RabbitMq则像是一支巨炮。 ;) - Hassan Syed
2
OP没有说明是否需要“bazooka”,所以我提供了我认为最受欢迎的那个。我已编辑我的答案,包括zeromq和ActiveMQ,并指向另一个关于该主题的SO问题。 - jterrace
2
我认为protobuf只是一种用于传输消息本身的可移植序列化库。它似乎没有提供任何远程过程调用(RPC)和进程间通信(IPC)的机制。 - Stefan

5
使用 zeromq,它足够简单易用。

1
不错的项目,文档也很好。感谢你指出这一点! - André Caron
确实非常棒。而且它看起来真正的便携、灵活和快速。 - Alexandre C.

2

另一个选择是使用ctypes模块,直接从Python代码中调用C代码,而不是将两个程序分别运行。


1
C进程是一个守护进程,一直在后台运行。 - Lee Treveil

1
你可以使用Google的GRPC来实现这个功能。

1
你的数据有多复杂?如果它很简单,我会将其序列化为字符串。如果它稍微复杂一些,我会使用JSON。TCP是一个很好的跨平台IPC传输协议。既然你说这种IPC很少见,性能并不是非常重要,那么TCP+JSON就足够了。

-3

我会告诉你创建一个DLL来管理两者之间的通信。Python将加载DLL并调用像getData()这样的方法,DLL将反过来与进程通信并获取数据。 那应该不难。 此外,您可以使用XML文件或SQLite数据库或任何数据库来查询数据。守护程序将更新DB,Python将继续查询。可能会有一个字段指示DB中的数据是否已由守护程序更新,然后Python将查询。 当然,这取决于性能和准确性因素!


14
因为我不想飞到日本才能吃寿司,而是可以打电话订购并让它送到家里。 :) - Lee Treveil
3
@Stefano 显然有批评之处... 我的反对票是因为这不是跨平台的解决方案(请参见标签)。 - schlamar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接