msgpage C++ : send raw pointer with MSGPACK_DEFINE - c++

I would like to send the following struct over msgpack.
struct MyStruct {
std::string name{""};
int* val{nullptr};
MSGPACK_DEFINE( name, val );
};
Thus far in all of my projects, the only way I've streamed with msgpack is using MSGPACK_DEFINE, then writing the struct to msgpack::sbuffer (and sending it). the MSGPACK_DEFINE macro complains that that perhaps I missed the "->" so I'm guessing it doesn't detect that it's a pointer.
Smart pointers seem to work though:
struct MyStruct {
std::string name{""};
std::shared_ptr<int> val{nullptr};
MSGPACK_DEFINE( name, val );
};
The caveat is that the receiver on the other end needs val to be a raw pointer. I would like to do this without converting on the receiving side. Any ideas?

You failed to explain why you wish to do this. Pointers are never meaningful when serialized (otherwise it is in-process data and there is no need to serialize).
Just pass the value that the pointer points to. If you need to represent "a number or NULL", then pass a struct containing an integer and boolean.
struct NullableInt {
int value{0};
bool null{true};
};

Related

QUdpSocket : I'm receiving a struct, how do I use it?

via a QUdpSocket, I know I'll receive datas which will contain only this struct:
typedef struct myStruct
{
int nb_trame;
std::vector<bool> vBool;
} myStruct;
but when I receive new datas, I receive a QByteArray right ?
So how can I use the received-struct ?
You can't entity-serialize a vector (your way of sending the struct is called entity-serialization). I mean, you can serialize it, but if you attempt to deserialize it this way you will not get a valid object.
You need to implement proper serialization.

Boost::visitor same data types several times

I try to implement a data structure from a protocol. To make sure the payload type fits the contained data I have a visitor function to get the type. In all other data structures there are differen types used in the variant, expect here in the payload.
enum class PayloadType : uint8_t {
Unsecured = 0,
Signed = 1,
Encrypted = 2,
Signed_External = 3,
Signed_And_Encrypted = 4
};
typedef ByteBuffer Unsecured;
typedef ByteBuffer Signed;
typedef ByteBuffer Encrypted;
typedef ByteBuffer SignedExternal;
typedef ByteBuffer SignedAndEncrypted;
typedef boost::variant<Unsecured, Signed, Encrypted, SignedExternal, SignedAndEncrypted> Payload;
Now the problem is, that every type in the visitor is the same (for example Signed is ab ByteBuffer like Encrypted is a ByteBuffer).
PayloadType get_type(const Payload& payload) {
struct PayloadVisitor : public boost::static_visitor <> {
void operator()(const Unsecured& unsecured){
mtype = PayloadType::Unsecured;
}
void operator()(const Signed& sign){
mtype = PayloadType::Signed;
}
void operator()(const Encrypted& encrypted){
mtype = PayloadType::Encrypted;
}
void operator()(const SignedExternal& external){
mtype = PayloadType::Signed_External;
}
void operator()(const SignedAndEncrypted& sign){
mtype = PayloadType::Signed_And_Encrypted;
}
PayloadType mtype;
};
PayloadVisitor visit;
boost::apply_visitor(visit, payload);
return visit.mtype;
}
Is there any way to make the different types distinguishable from each other?
I found that it works, if i put them into structs like:
struct SignedExternal {
ByteBuffer buf;
}
struct Signed {
ByteBuffer buf;
}
and so on..
But then its quite long-winded to work with the data types.
Maybe there is an easy way to achive this?
The problem here is that you try to use typedef for something that it isn't: It does not declare a new type. (I think that might have changed for c++11, since that allows typedef'ed templates). If someone can find the reference in the standards, I'd be grateful, but for now, from cppreference.com:
The typedef-names are aliases for existing types, and are not declarations of new types.
You simply don't get a new type by doing a typedef. Maybe inheritance might help you, giving you "real" new types, but I don't know whether that is a good idea in your overall application. It probably is -- your problem matches the idea of polymorphism just soooo nicely.
Generally, c++ is statically typed, so the idea of using the type of an object as part of the information might not be the best. Generally, you might just want your buffer class to have a field "type" that refers to your enum and act based on that field's value. But that's just poor man's inheritance. If you want to have poor C man's inheritance, do the same, but save a function pointer that "does the right thing" along with your buffer.
You can use a strong typedef
BOOST_STRONG_TYPEDEF(SignedExternal, ByteBuffer);
There's two of them, one in Bosot Utility and one in Boost Serialization as I remember.
One of the two has more features (like lifting some operators, like comparison/equality as I remember).

Packet cast to struct with multiple dynamic arrays

I'm currently working on a Client/Server application, sending packets via TCP.
To read the incoming packet, I do something like this:
struct SomeRandomStruct
{
int nVal1;
int nVal2;
};
SomeRandomStruct* pStruct = reinterpret_cast<SomeRandomStruct*>(pBuffer);
Right now there's a small problem. Let's say I have a struct like this
struct SomeNewStruct
{
int nNameLen;
int nPassLen;
char szName[];
char szPass[];
};
Since the size/length of szName & szPass is sent in the same packet, is there a way I can set its size ,,within the reinterpret_cast" or do I have to read the packet manually?
Friendly warning:
stop!
Consider something like google protocol buffers to encode messages for you in a cross-platform and safe way.
Here are some reasons why:
How big is an int? On your machine? today? tomorrow? It's undefined in the c++ standard.
What is the binary representation of an int? Is it the same on the machine sending and the machine receiving? Will it always be? (If you think 'yes' then you're wrong). Again the c++ standard has nothing to say on the matter.
What is the padding between data members in the struct? Is it the same for all compilers on all hosts? (answer: no)
ask yourself why functions like htons() exist. They are there because not all machines are the same, but the communication between them must be.
I could go on...
As your question is tagged C++, I'd propose you to do dynamic allocation in constructor and deallocation in destructor. That way, you could have simply pointers in your struct :
struct struct SomeNewStruct {
int nNameLen;
int nPassLen;
char *szName;
char *szPass;
SomeNewStruct(int nameLen , int passLen) {
// set and alloc...
}
SomeNewStruct(SomeNewStruct &src) {
// alloc and copy
}
~SomeNewStruct() {
// dealloc ...
}
}
You could even use std::string for szName and SzPass letting the STL deal with those low level allocation details :
struct struct SomeNewStruct {
int nNameLen;
int nPassLen;
std::string szName;
std::string szPass;
}

generic message dispatching library?

Is there a standard way to get rid of the switch/case block in a read loop?
i.e.
enum msg_type
{
message_type_1,
//msg types
}
struct header
{
msg_type _msg_type;
uint64_t _length;
}
struct message1
{
header _header;
//fields
}
struct message2
{
header _header;
//fields
}
//socket read loop
void read(//blah)
{
//suppose we have full message here
char* buffer; //the buffer that holds data
header* h = (header*)buffer;
msg_type type = h->_msg_type;
switch(type)
{
case msg_type_1:
message1* msg1 = (message1*)buffer;
//Call handler function for this type
//rest
}
}
this means that I have to inherit from a handler container base class which is of the form:
class handler_container_base
{
public:
virtual void handle(message1* msg){}
virtual void handle(message2* msg){}
//etc
}
and pass an object of that type to where the message loop can see and ask him to call those back.
One problem is, even when I want to implement and register only one handler for a single type I have to inherit from this class.
Another is this just looks ugly.
I was wondering if there are existing libraries which handle this problem (should be free). Or is there no better way of doing this rather than like this?
Other approaches that avoid inheritance are:
For a closed set of types:
Use a variant:
variant<message1_t, message2_t> my_message;
With a visitor you can do the rest. I recommend boost.variant.
You can also use a boost::any, for an open set of types, and copy the messages around at runtime.At some point you will have to cast back to the original type, though.
Another solution goes along the lines of Poco.DynamicAny, which will try to convert, to the type on the left in an assignment, similar to a dynamic language. But you need to register converters yourself for your types.

C++ design - Network packets and serialization

I have, for my game, a Packet class, which represents network packet and consists basically of an array of data, and some pure virtual functions
I would then like to have classes deriving from Packet, for example: StatePacket, PauseRequestPacket, etc. Each one of these sub-classes would implement the virtual functions, Handle(), which would be called by the networking engine when one of these packets is received so that it can do it's job, several get/set functions which would read and set fields in the array of data.
So I have two problems:
The (abstract) Packet class would need to be copyable and assignable, but without slicing, keeping all the fields of the derived class. It may even be possible that the derived class will have no extra fields, only function, which would work with the array on the base class. How can I achieve that?
When serializing, I would give each sub-class an unique numeric ID, and then write it to the stream before the sub-class' own serialization. But for unserialization, how would I map the read ID to the appropriate sub-class to instanciate it?
If anyone want's any clarifications, just ask.
-- Thank you
Edit: I'm not quite happy with it, but that's what I managed:
Packet.h: http://pastebin.com/f512e52f1
Packet.cpp: http://pastebin.com/f5d535d19
PacketFactory.h: http://pastebin.com/f29b7d637
PacketFactory.cpp: http://pastebin.com/f689edd9b
PacketAcknowledge.h: http://pastebin.com/f50f13d6f
PacketAcknowledge.cpp: http://pastebin.com/f62d34eef
If someone has the time to look at it and suggest any improvements, I'd be thankful.
Yes, I'm aware of the factory pattern, but how would I code it to construct each class? A giant switch statement? That would also duplicade the ID for each class (once in the factory and one in the serializator), which I'd like to avoid.
For copying you need to write a clone function, since a constructor cannot be virtual:
virtual Packet * clone() const = 0;
Which each Packet implementation implement like this:
virtual Packet * clone() const {
return new StatePacket(*this);
}
for example for StatePacket. Packet classes should be immutable. Once a packet is received, its data can either be copied out, or thrown away. So a assignment operator is not required. Make the assignment operator private and don't define it, which will effectively forbid assigning packages.
For de-serialization, you use the factory pattern: create a class which creates the right message type given the message id. For this, you can either use a switch statement over the known message IDs, or a map like this:
struct MessageFactory {
std::map<Packet::IdType, Packet (*)()> map;
MessageFactory() {
map[StatePacket::Id] = &StatePacket::createInstance;
// ... all other
}
Packet * createInstance(Packet::IdType id) {
return map[id]();
}
} globalMessageFactory;
Indeed, you should add check like whether the id is really known and such stuff. That's only the rough idea.
You need to look up the Factory Pattern.
The factory looks at the incomming data and created an object of the correct class for you.
To have a Factory class that does not know about all the types ahead of time you need to provide a singleton where each class registers itself. I always get the syntax for defining static members of a template class wrong, so do not just cut&paste this:
class Packet { ... };
typedef Packet* (*packet_creator)();
class Factory {
public:
bool add_type(int id, packet_creator) {
map_[id] = packet_creator; return true;
}
};
template<typename T>
class register_with_factory {
public:
static Packet * create() { return new T; }
static bool registered;
};
template<typename T>
bool register_with_factory<T>::registered = Factory::add_type(T::id(), create);
class MyPacket : private register_with_factory<MyPacket>, public Packet {
//... your stuff here...
static int id() { return /* some number that you decide */; }
};
Why do we, myself included, always make such simple problems so complicated?
Perhaps I'm off base here. But I have to wonder: Is this really the best design for your needs?
By and large, function-only inheritance can be better achieved through function/method pointers, or aggregation/delegation and the passing around of data objects, than through polymorphism.
Polymorphism is a very powerful and useful tool. But it's only one of many tools available to us.
It looks like each subclass of Packet will need its own Marshalling and Unmarshalling code. Perhaps inheriting Packet's Marshalling/Unmarshalling code? Perhaps extending it? All on top of handle() and whatever else is required.
That's a lot of code.
While substantially more kludgey, it might be shorter & faster to implement Packet's data as a struct/union attribute of the Packet class.
Marshalling and Unmarshalling would then be centralized.
Depending on your architecture, it could be as simple as write(&data). Assuming there are no big/little-endian issues between your client/server systems, and no padding issues. (E.g. sizeof(data) is the same on both systems.)
Write(&data)/read(&data) is a bug-prone technique. But it's often a very fast way to write the first draft. Later on, when time permits, you can replace it with individual per-attribute type-based Marshalling/Unmarshalling code.
Also: I've taken to storing data that's being sent/received as a struct. You can bitwise copy a struct with operator=(), which at times has been VERY helpful! Though perhaps not so much in this case.
Ultimately, you are going to have a switch statement somewhere on that subclass-id type. The factory technique (which is quite powerful and useful in its own right) does this switch for you, looking up the necessary clone() or copy() method/object.
OR you could do it yourself in Packet. You could just use something as simple as:
( getHandlerPointer( id ) ) ( this )
Another advantage to an approach this kludgey (function pointers), aside from the rapid development time, is that you don't need to constantly allocate and delete a new object for each packet. You can re-use a single packet object over and over again. Or a vector of packets if you wanted to queue them. (Mind you, I'd clear the Packet object before invoking read() again! Just to be safe...)
Depending on your game's network traffic density, allocation/deallocation could get expensive. Then again, premature optimization is the root of all evil. And you could always just roll your own new/delete operators. (Yet more coding overhead...)
What you lose (with function pointers) is the clean segregation of each packet type. Specifically the ability to add new packet types without altering pre-existing code/files.
Example code:
class Packet
{
public:
enum PACKET_TYPES
{
STATE_PACKET = 0,
PAUSE_REQUEST_PACKET,
MAXIMUM_PACKET_TYPES,
FIRST_PACKET_TYPE = STATE_PACKET
};
typedef bool ( * HandlerType ) ( const Packet & );
protected:
/* Note: Initialize handlers to NULL when declared! */
static HandlerType handlers [ MAXIMUM_PACKET_TYPES ];
static HandlerType getHandler( int thePacketType )
{ // My own assert macro...
UASSERT( thePacketType, >=, FIRST_PACKET_TYPE );
UASSERT( thePacketType, <, MAXIMUM_PACKET_TYPES );
UASSERT( handlers [ thePacketType ], !=, HandlerType(NULL) );
return handlers [ thePacketType ];
}
protected:
struct Data
{
// Common data to all packets.
int number;
int type;
union
{
struct
{
int foo;
} statePacket;
struct
{
int bar;
} pauseRequestPacket;
} u;
} data;
public:
//...
bool readFromSocket() { /*read(&data); */ } // Unmarshal
bool writeToSocket() { /*write(&data);*/ } // Marshal
bool handle() { return ( getHandler( data.type ) ) ( * this ); }
}; /* class Packet */
PS: You might dig around with google and grab down cdecl/c++decl. They are very useful programs. Especially when playing around with function pointers.
E.g.:
c++decl> declare foo as function(int) returning pointer to function returning void
void (*foo(int ))()
c++decl> explain void (* getHandler( int ))( const int & );
declare getHandler as function (int) returning pointer to function (reference to const int) returning void