Update 20200318 Share data between C and Python with this messaging library.md

This commit is contained in:
SilentDawn 2020-07-28 02:52:43 +08:00 committed by GitHub
parent 505f2a0e40
commit 1d3eca7867
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -14,7 +14,7 @@ ZeroMQ 是一个快速灵活的消息库,用于数据收集和不同语言间
作为软件工程师,我有多次在要求完成指定任务时感到毛骨悚然的经历。其中一次是要写个接口,用于控制一些新的底层硬件间的对接,接口实现形式分别是 C 和 云底层组件,而后者主要是 Python。
实现的方式之一是 [用 C 写扩展模块][2], which Python supports by design. 快速浏览文档后发现,这需要编写大量的 C 代码。这种做的话,在有些情况下效果还不错,但不是我想要的方式。另一种方式就是将两个任务放在不同的进程中,以使用 [ZeroMQ 消息库][3] 在进程间交换信息的方式实现数据的共享。
实现的方式之一是 [用 C 写扩展模块][2]Python 支持 C 扩展的调用。快速浏览文档后发现,这需要编写大量的 C 代码。这样做的话,在有些情况下效果还不错,但不是我想要的方式。另一种方式就是将两个任务放在不同的进程中,以使用 [ZeroMQ 消息库][3] 在进程间交换信息的方式实现数据的共享。
在引入 ZeroMQ 之前,我选择了编写扩展的方式,试图解决这个场景的需求。这种方式不算太差,但非常复杂和费时。现在为了避免那些问题,我细分出一个系统作为独立的进程运行,专门用于交换通过 [通信套接字][4] 发送的消息所承载的数据。这样,不同的编程语言可以共存,每个进程也变简单了,同时也容易调试。
@ -42,23 +42,23 @@ Fedora 系统上的安装方法:
```
`$ dnf install clang zeromq zeromq-devel python3 python3-zmq`
$ dnf install clang zeromq zeromq-devel python3 python3-zmq
```
Debian 和 Ubuntu 系统上的安装方法:
```
`$ apt-get install clang libzmq5 libzmq3-dev python3 python3-zmq`
$ apt-get install clang libzmq5 libzmq3-dev python3 python3-zmq
```
如果有问题,参考对应项目的安装指南(上面附有链接)。
### 编写硬件接口库
因为这里针对的是个假定的场景,本教程虚构了包含两个函数操作库:
因为这里针对的是个设想的场景,本教程虚构了包含两个函数的操作库:
* **fancyhw_init()** 用来初始化(假定的)硬件
* **fancyhw_init()** 用来初始化(设想的)硬件
* **fancyhw_read_val()** 用于返回从硬件读取的数据
@ -88,7 +88,7 @@ int16_t fancyhw_read_val(void)
#endif
```
这个库可以模拟你要在不同语言实现的组件间交换的数据,有劳随机数发生器
这个库可以模拟你要在不同语言实现的组件间交换的数据,中间有劳随机数发生器。
### 设计 C 接口
@ -136,7 +136,7 @@ int main(void)
```
`fancyhw_init(INIT_PARAM);`
fancyhw_init(INIT_PARAM);
```
ZeroMQ 库需要实打实的初始化。首先,定义对象 **context**,它是用来管理全部的套接字的:
@ -157,7 +157,7 @@ if (!context)
```
`void *data_socket = zmq_socket(context, ZMQ_PUB);`
void *data_socket = zmq_socket(context, ZMQ_PUB);
```
套接字需要绑定到一个具体的地址,这样客户端就知道要连接哪里了。本例中,使用了 [TCP 传输层][15](当然也有 [其它选项][16],但 TCP 是不错的默认选择):
@ -411,7 +411,7 @@ int main(void)
```
`$ clang -std=c99 -I. hw_interface.c -lzmq -o hw_interface`
$ clang -std=c99 -I. hw_interface.c -lzmq -o hw_interface
```
如果没有编译错误你就可以运行这个接口了。贴心的是ZeroMQ **PUB** 套接字可以在没有任何应用发送或接受数据的状态下运行,这简化了使用复杂度,因为这样不限制进程启动的次序。
@ -443,7 +443,7 @@ Read 16 data values
```
`$ python3 -m pip install zmq`
$ python3 -m pip install zmq
```
另一个就是 [**struct** 库][21],用于解码二进制数据。这个库是 Python 标准库的一部分,所以不需要使用 **pip** 命令安装。
@ -506,7 +506,7 @@ with zmq.Context() as context:
```
`binary_topic, data_buffer = socket.recv().split(b' ', 1)`
binary_topic, data_buffer = socket.recv().split(b' ', 1)
```
#### 解码消息
@ -534,7 +534,7 @@ print("\tpacket size: {:d}".format(packet_size))
```
`struct_format = "{:d}h".format(packet_size)`
struct_format = "{:d}h".format(packet_size)
```
将二进制数据串转换为可直接打印的一系列数字: