I have a c function that publish data to a c++ subscriber, now I want to migrate this c function to Python:
void setup_msg_publish() {
int r;
zmqcontext = zmq_ctx_new();
datasocket = zmq_socket(zmqcontext, ZMQ_PUB);
r = zmq_bind(datasocket, "tcp://*:44000");
if (r == -1) {
printf(zmq_strerror(errno));
}
}
void publishdata(int x, int y) {
if (datasocket == 0) {
setup_msg_publish();
}
zmq_data zd;
zd.msgType = int 0;
zd.x = x;
zd.y = y;
size_t len = sizeof(zd);
int res = zmq_send(datasocket, &zd, len, NULL);
assert(res == len);
}
I've tried to implement this in Python:
import zmq
import pickle
from collections import namedtuple
Data = namedtuple("Data", "msgType x y")
def send_zmq():
data = Data("0", "1", "2")
msg = pickle.dumps(data)
context = zmq.Context()
socket = context.socket(zmq.REQ)
socket.connect("tcp://127.0.0.1:44000")
socket.send(msg)
For debug purposes I can recive the data with Python like this:
import zmq
import pickle
context = zmq.Context()
socket = context.socket(zmq.REP)
socket.bind("tcp://127.0.0.1:44000")
while True:
message = socket.recv()
data = pickle.loads(message)
print(data)
But I don't receive anything in my c++ code (it just prints no data
):
#include "View.h"
#include <iostream>
#include <thread>
#include <chrono>
View::View() :
viewSubscriber(zmqcontext, ZMQ_SUB)
{
unsigned _int16 msgType = 0;
viewSubscriber.connect("tcp://127.0.0.1:44000");
//viewSubscriber.setsockopt(ZMQ_SUBSCRIBE, &msgType, sizeof(msgType));
viewSubscriber.setsockopt(ZMQ_SUBSCRIBE, "", 0);
std::cout << msgType;
}
void View::run() {
using namespace std;
bool received_view_data = false;
bool checkForMore = true;
zmq_view data;
while (checkForMore) {
zmq::message_t msg;
//cout << &msg;
if (viewSubscriber.recv(&msg, ZMQ_NOBLOCK)) {
received_view_data = true;
memcpy(&data, msg.data(), sizeof(data));
cout << &data.x;
}
else {
std::this_thread::sleep_for(std::chrono::milliseconds(500));
cout << "no data \n";
}
}
}
int main(){
View *app = new View();
app -> run();
return 0;
}
Any ideas what to fix so I receive the data in the namedTuple on the c++ side? Could it be that the c++ "needs to know more" about the type of each attribute of the namedTuple (if that is the case how do I specify whether the data is a double or int etc?)?
The solution was found after testing to go from C++ -> Python thank you J_H for the idea. Instead of using a namedtuple a packed struct was used.
import zmq
import struct
def send_zmq():
struct_format = 'Idd'
msg_type = 0
x = 1.0
y = 1.0
msg = struct.pack(struct_format, msg_type, x, y)
context = zmq.Context()
socket = context.socket(zmq.REQ)
socket.connect("tcp://127.0.0.1:44000")
socket.send(msg)