C++とPython間の通信構造体

C++Python間で同じ構造体を用いてTCP通信をしたかったのでまとめ(ROS最高!!!)

環境

macOS 11.6

C++

gcc 13.0.0
TCP通信部はlwipで実装

Python

Python 3.9.6
TCP通信部はsocketで実装
C++は標準の構造体,Pythonはctypesの構造体を使用

構造体定義

C++

#pragma pack(push, 1)
struct TcpHeader {
    uint32_t size;
    uint8_t type;
    TcpHeader(uint32_t size = 0, uint8_t type = 0) : 
        size(size),
        type(type) {}
};
struct PacketControlDataReq {
    TcpHeader header;
    uint8_t arm_id;
    ControlData control_data;
    PacketControlDataReq() : 
        header(sizeof(PacketControlDataReq), MAINTE_TO_ROBOT_CONTROL_DATA) {}
};
struct PacketRobotInfoReq {
    TcpHeader header;
    uint8_t num_arm;
    uint8_t num_joint;
    PacketRobotInfoReq() : 
        header(sizeof(PacketRobotInfoReq), ROBOT_TO_MAINTE_ROBOT_INFO),
        num_arm(ArmId::NUM_ARM),
        num_joint(NUM_JOINT) {}
};
#pragma pack(pop)

Python

class TcpHeader(Structure):
    _pack_ = 1
    _fields_ = [
        ('size', c_uint32),
        ('type', c_uint8)
    ]
    def __init__(self, size = 0, type = 0):
        self.size = size
        self.type = type
class PacketControlDataReq(Structure):
    _pack_ = 1
    _fields_ = [
        ('header', TcpHeader),
        ('arm_id', c_uint8),
        ('control_data', ControlData)
    ]
    def __init__(self):
        self.header = TcpHeader(sizeof(PacketControlDataReq), PacketType.MAINTE_TO_ROBOT_CONTROL_DATA)
class PacketArmInfoReq(Structure):
    _pack_ = 1
    _fields_ = [
        ('header', TcpHeader),
        ('num_arm', c_uint8),
        ('num_joint', c_uint8)
    ]
    def __init__(self):
        self.header = TcpHeader(sizeof(PacketArmInfoReq), PacketType.ROBOT_TO_MAINTE_ARM_INFO)
        self.num_arm = 0
        self.num_joint = 0

C++ >> Python

送信側(C++)

PacketRobotInfoReq robot_info_req;
int err = send(sock, &robot_info_req, sizeof(PacketRobotInfoReq), 0);

受信側(python)

arm_info = PacketArmInfoReq()
memmove(addressof(arm_info), data, sizeof(arm_info))
print("num_arm = {}, num_joint = {}".format(arm_info.num_arm, arm_info.num_joint))

Python >> C++

送信側(python)

control_data = PacketControlDataReq()
client.send(control_data)

受信側(C++)

std::array<char, 2048> rx_buffer;
int len = recv(sock, rx_buffer.data(), rx_buffer.size(), 0);
PacketControlDataReq control_data_req;
memmove(&control_data_req, rx_buffer.data(), sizeof(control_data_req));
printf("arm_id = %d", control_data_req.arm_id);