Skip to content

Cross-language Messaging with ZeroMQ: C++, Python, and Fortran

🧩 Setup

We’ll use ZeroMQ’s PUSH/PULL pattern to build a minimal, language-agnostic messaging microservice.

Each sender (written in Python, C++, or Fortran) pushes 64-bit values to a single receiver.

📦 Dependencies

Linux (Debian/Ubuntu):

sudo apt-get install libzmq3-dev
````

#### Python:

```bash
python3 -m pip install pyzmq

Fortran ZMQ bindings:

Install fzmq:

git clone https://github.com/richsnyder/fzmq && cd fzmq
mkdir build && cd build
cmake -DBUILD_DOCS=OFF ../
sudo make install

🛰️ Sender: Python

#!/usr/bin/python3
import zmq

ctx = zmq.Context()
sock = ctx.socket(zmq.PUSH)
sock.connect("tcp://localhost:5555")

for x in range(100):
    sock.send(x.to_bytes(8, 'little'))

Highlights:

  • Sends 8-byte integers in little-endian format
  • Easy for testing other receivers

🛰️ Sender: C++

#include <zmq.h>
#include <cstdint>
#include <cstring>

int main() {
    void* ctx = zmq_ctx_new();
    void* sock = zmq_socket(ctx, ZMQ_PUSH);
    zmq_connect(sock, "tcp://localhost:5555");

    for(uint64_t x = 0; x < 100; ++x)
        zmq_send(sock, &x, sizeof(x), 0);

    zmq_close(sock);
    zmq_ctx_term(ctx);
}

Highlights:

  • Sends raw uint64_t values (8 bytes)
  • Matches Python format

🛰️ Sender: Fortran

program send
  use fzmq
  implicit none

  type(zmq_context) :: context
  type(zmq_socket)  :: sock
  integer(kind=8)   :: x
  integer           :: rc

  context = zmq_ctx_new()
  sock = zmq_socket(context, ZMQ_PUSH)
  call zmq_connect(sock, "tcp://localhost:5555")

  do x = 0, 99
    call zmq_send(sock, x, 8, 0)
  end do

  call zmq_close(sock)
  call zmq_ctx_term(context)
end program send

Highlights:

  • Uses fzmq bindings
  • Sends binary 64-bit integers

🎯 Receiver: C++

#include <zmq.h>
#include <cstdint>
#include <cstdio>

int main() {
    void* ctx = zmq_ctx_new();
    void* sock = zmq_socket(ctx, ZMQ_PULL);
    zmq_bind(sock, "tcp://*:5555");

    for(uint64_t x; true;) {
        zmq_recv(sock, &x, sizeof(x), 0);
        printf("recv: %lu\n", x);
    }

    zmq_close(sock);
    zmq_ctx_term(ctx);
}

Highlights:

  • Pulls 64-bit integers from any connected sender
  • No language-specific deserialization required

✅ Summary

ZeroMQ’s PUSH/PULL pattern makes multi-language IPC a breeze.

Role Language Notes
Sender Python Uses pyzmq, clean syntax
Sender C++ Raw zmq_send of binary integers
Sender Fortran Uses fzmq bindings
Receiver C++ Prints values from all senders

Run the receiver first, then launch any combination of senders. Messages will stream in regardless of language. No serialization frameworks, no boilerplate.