Accessing union elements in C++ - c++

I have been implementing a communication protocol in C++ and I have decided to model one packet in below given manner.
union control_pkt_u{
struct pkt_parts_t{
uint8_t header[3]; // Control packet header
uint8_t payload[NO_PYLD_BYTES_IN_CONTROL_PACKET]; // Control packet payload
};
uint8_t pkt_array[NO_BYTES_IN_PACKET];
};
As soon as I need to access to the elements of the union
pkt.pkt_parts_t.header[0] = APP_MSG_DEB;
I receive an error during compilation:
invalid use of struct Manager::control_pkt_u::pkt_parts_t
Please can anybody tell me what I am doing wrong?

Because you are just defining a struct in your control_pkt_u union and it is just a declaration, it is not initialised when you create an object from it. You need to declare it as a member like this and reach your member pkt_parts_.
union control_pkt_u {
struct pkt_parts_t {
uint8_t header[3]; // Control packet header
uint8_t payload[NO_PYLD_BYTES_IN_CONTROL_PACKET]; // Control packet payload
} pkt_parts_;
uint8_t pkt_array[NO_BYTES_IN_PACKET];
};
pkt.pkt_parts_.header[0] = APP_MSG_DEB;

You can change the struct definiation to this by using Anonymous structure:
struct {
uint8_t header[3]; // Control packet header
uint8_t payload[NO_PYLD_BYTES_IN_CONTROL_PACKET]; // Control packet payload
} pkt_parts_t;
Then you don't need to change other code.

Related

Access struct elements in a class linitalizer list

I'm working on an embedded-system project using EFM32GG11 series micro-controller. In project I've to read data from multiple serial port, process the data and forward the data to server via Ethernet.
I've created a class that will handle serial port. Multiple object of this class will be created.
I've created a constructor with initialize list. I've a question : Is their a way to directly access structure member in initialization list? - uart_init.baudRate(baud_rate)
class SerialPort {
public :
enum PortList{
COM1, //RS-232
COM2 //RS-232 -- 8 more ports
};
private:
PortList port_no;
UARTDRV_Init_t uart_init;
uint32_t baud_rate;
char parity;
uint8_t stop_bit;
bool single_line_mode;
uint16_t block_time; //in milli-seconds
public:
SerialPort(PortList port_no, uint16_t baud_rate, char parity, uint8_t stop_bit,
bool single_line_mode, uint16_t block_time) : port_no(port_no), uart_init.baudRate(baud_rate), parity(parity), stop_bit(stop_bit), single_line_mode(single_line_mode),
block_time(block_time)
{
//Further processing post initialization
}
};
UARTDRV_Init_t Strurcture :
typedef struct {
USART_TypeDef *port; ///< The peripheral used for UART
uint32_t baudRate; ///< UART baud rate
} UARTDRV_InitUart_t;
You can use designated initializers (since C++20) to specify the member to be initialized. E.g.
SerialPort(PortList port_no, uint16_t baud_rate, char parity, uint8_t stop_bit,
bool single_line_mode, uint16_t block_time) : port_no(port_no), uart_init {.baudRate=baud_rate}, parity(parity), stop_bit(stop_bit), single_line_mode(single_line_mode),
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
block_time(block_time)
{
//Further processing post initialization
}
Before C++17, we can only initialize the data member itself in member initializer list and can't specify its subobject further more.
If you know the what the default for port should be, you could do it this way, assuming port is initialized to nullptr or something:
SerialPort(PortList port_no, uint16_t baud_rate, char parity, uint8_t stop_bit,
bool single_line_mode, uint16_t block_time) : port_no(port_no), uart_init {nullptr, baud_rate}, parity(parity), stop_bit(stop_bit), single_line_mode(single_line_mode),
block_time(block_time)
{
...
}

Packet wrangling from C to C++ or... how Neither Variant nor Any is a Union

The problem in a nutshell: I'm considering a rewrite of some packet handling code for a UDP protocol ... from C to C++. Obviously, I can just use the structures that I had with C to model the data, but then what would be the point? So, for the sake of argument, we have:
struct { uint8:2 type; uint8:6 con_id; uint16 seq_num } packet_header;
struct { packet_header ph; uint16 command; } control_packet;
struct { packet_header ph; uchar8 data[DATASIZE]; } data_packet;
In this case, "type" is 0 for data, 1 for control, 2 for encrypted data and 3 for encrypted control. There would also be structs reprenting each of the control packets, for argument, lets say "open" and "close".
Now... I would normally have a type that the function that fetches the packet returns and the function that sends accepts:
struct {
size_t pkt_len;
union {
uchar8 raw_packet[DATASIZE];
packet_header ph;
control_packet cp;
control_open_packet cop;
control_close_packet ccp;
data_packet dp;
} p;
} packet;
... this is all simplified for argument... but the point is: when sending a packet, we want to create a packet of a certain type and send a generic packet. Conversely, when receiving a packet, you want to receive a generic packet and and cast it to more specific types as you classify it.
So where's the question? My question is: if Variant and Any are not appropriate ways to express this, what are? Am I stuck with union in this case? Certainly I don't violate the stipulation of POD types (so far) for the union. I've been scouring both C++11 and Boost (and to some extent looking at C++14 ... although I'm stuck with C++11) and I don't see offered solutions.
You can use both union as it is in your example or class hierarchy with packet_header a the top and specific derived classes for each type of the packet:
struct packet_header { uint8:2 type; uint8:6 con_id; uint16 seq_num };
struct control_packet : packet_header { uint16 command; };
struct data_packet: packet_header { uchar8 data[DATASIZE]; };
struct packet
{
size_t pkt_len;
union
{
uchar8 raw_packet[DATASIZE];
packet_header ph;
control_packet cp;
control_open_packet cop;
control_close_packet ccp;
data_packet dp;
};
};
Maybe you need to seek for elegance and flexibility in the code that handles your packets. I doubt that defining data in some other way (using boost or using C++17 features) will lead to a considerable gain.
Note the anonymous union in the struct packet. It allows accessing fields of specific packet types directly. C++ style expects the name of the struct directly after the struct keyword.

Design pattern for message packet header

I am writing my own messaging API using libevent. The data is wrapped by a packet structure which contains a packet body of data byte array and a packet header that contains the entire packet size information (for the reason to invoke callback at a complete stream).
class PacketHeader {
size_t packet_size;
};
class Packet {
PacketHeader header;
uint8_t* body;
};
However, I wanna users be able to customize their own PacketHeader, while I can handle the underlying size information for messaging. What is the best practice to do this? Should I use inheritance or pure virtual abstraction (interface class). I was thinking about the following but not sure if it is the best practice.
template <class Derived>
class PacketHeader{
size_t packet_size;
size_t header_size() const {return sizeof(Derived);}
}
Instead of all the inheritance stuff, why not make the packets self describing, i.e. something like:
struct packet_header {
int16_t size; // size_t is too big
uint8_t header; // header size
uint8_t type; // header type, some sort of id for header/message
};
Then users can define their own header types with sizes, a message would be composed as follows:
[ ][ ][ ]<--custom header-->[--body--]
So the custom header block is optional and the size is specified in the packet header. Then allow user specific code to decode the header appropriately.

converting struct to general message format to be passed to UDP

I have a C++ struct for an update packet to be exchanged between servers, and another struct to implement information about neighbors, and a vector of struct neighbor is inside update packet.
struct neighbor;
struct update_packet {
uint16_t num_update_fields;
uint16_t port;
uint32_t IP;
vector<struct neighbor> neighbors;
update_packet(char * IPstr, int port) :
num_update_fields(num_nodes),
IP(IP_to_int(IPstr)), port((uint16_t) port)
{ };
};
struct neighbor {
uint32_t IP;
uint16_t port;
int16_t nil;
uint16_t server_id;
uint16_t cost;
neighbor(char * IPstr, uint16_t port, uint16_t server_id, uint16_t cost) :
IP(IP_to_int(IPstr)), port(port), nil(0),
server_id(server_id), cost(cost) { };
};
I want to exchange this struct in general message format (like IP datagram, for example) through UDP sockets and read the information in the message on the receiving end.
How can I achieve this? Is my design for the structs a poor design for my purpose?
What you're asking about is serialization. At it's simplest, if you have a POD type and know that the machines at both ends are the same type you can just cast and send:
struct Foo {
uint32_t a;
uint16_t p;
};
Foo f { 1, 2 };
sendto(targetFD, reinterpret_cast<const char*>(&f), sizeof(f), 0);
Your structure couldn't be used this way because of the vector. The data in a vector is dynamically allocated so it isn't laid out with the rest of the structure. If you need a variable length field like this, an array (or a std::array) along with an indicator of the number of elements would be useful.
Casting structures like this is fast but not really portable. If you want to be able to pass to other languages or platforms you would prefer a serialization format. Google's Protocol Buffers (https://code.google.com/p/protobuf/) and several other serialization libraries are designed to allow this.
Slightly more c++ style serialization and deserialization is desribed in this article - https://rodgert.github.io/2014/09/09/type-driven-wire-protocols-with-boost-fusion-pt1/

C++ Struct - Define Minimum Size

Is there a C++ (or MSVC) method of automatically padding a struct to a minimum size? For example, imagine the following pseudo-code:
#pragma pad(256) // bytes
struct SETUPDATA {
int var1;
double var2;
};
where sizeof(SETUPDATA) = 256 bytes
The goal here being, during development this struct's members can change without changing the footprint size at runtime.
You can use a union
struct SETUPDATA {
union { struct your_data; char [256]; }
}
or something like this. This ensures it's at least 256 but only as long as your_data is not larger.
You can also add a simple assert after that just does a compiler check assert(sizeof(struct SETUPDATA) == 256)
One way is to inherit from your "real" structure and use sizeof() to make up the padded structure, for example:
struct blah_real
{
int a;
};
struct blah : public blah_real
{
private:
char _pad[256 - sizeof(blah_real)];
};
You could use #ifdef DEBUG to only do this in the debug build and just use the real structure in release build.
The first thing you have ot ask yourself is why your application cares if the struct size changes. That indicate fragility to future changes and your design may be better served by instead allowing the application to seamlessly work in the face of struct size changes.
Perhaps you're trying to serialize the data directly and don't want to face changes in the format, but in that case you're already tying yourself to one specific representation of the structure in memory. For example support the size of one of the builtin-type members changes due to a compiler upgrade or options.
But let's say you really do want to do this.
Just wrap the data in an impl and pad the real struct:
struct SetupData
{
struct Impl
{
int var1;
double var2;
};
Impl impl_;
unsigned char pad_[256 - sizeof(Impl)];
};