3

Just a little background for the strange question: I have a network framwork (RTI DDS) which has a C serialisation function which takes a pointer and converts a C struct to a string.

It also (and is also designed to work) with C++ classes. But if I make a C++ class polymorphic by adding a virtual function this serialisation funktion segfaults or sometimes even worse provides wrong output.

I assume that it internally makes assumptions about the memory layout of the struct.

Is it possible to get a raw C pointer from a polymorphic C++ object?

I know that I could just create every struct twice, once polymorphic and once non-polymorphic, but this would lead to an insane amount of glue code.

Currently I am out of ideas.

Some technical background: The C function is in the RTI DDS Source package:

DynamicData.c DDS_ReturnCode_t DDS_DynamicData_to_cdr_buffer(...) { ..

ashiquzzaman33
  • 5,781
  • 5
  • 31
  • 42
Andreas Pasternak
  • 1,250
  • 10
  • 18
  • I don't think vtable implementation is standard across compilers. I think you have to know size of your class and exact offsets if you want to do it at run time. Just my logical guess. – Misgevolution Sep 24 '15 at 15:06
  • `It also (and is also designed to work) with C++ classes` I find it hard to believe. In C++, unless a class/struct is standard layout, it is very easy to enter UB land once you start messing with the internal representation of the data. – sbabbi Sep 24 '15 at 15:28
  • I guess, the question is what is the polymorphic part there. Do you need it? If you do, I find it hard to believe any serialization trick will help you, because you will loose polymorphism. And if you do not need it, why do you have virtual functions in the first place? – SergeyA Sep 24 '15 at 16:04
  • @SergeyA: What have in DDS is some kind of union type. So I fill in in this union type all classes in the inheritance tree. Then I use typeid to compare the type of the input object with the classes in the union and then I dynamic cast to the correct type that then will be serialized. – Andreas Pasternak Sep 24 '15 at 16:14

2 Answers2

4

You could add a non-virtual base struct containing only the data:

struct DataXYBase {
    int data1;
    double data2;
};

class VirtualBaseClass : public DataXYBase {
    virtual void Function1();
};

class DerivedClass : public VirtualBaseClass {
    virtual void Function1();
};

and then cast to DataXYBase before passing it to the serialization function.

alain
  • 11,939
  • 2
  • 31
  • 51
3

I think you should bundle all data in POD structs (which probably can inherit from each other) and all accessors/logic in polymorphic classes which contain the data structs either as members (or possibly even via inheritance). You would serialize only the data part and provide trivial constructors for your polymorphic classes from a data structure.

That should limit the amount of necessary glue and still retain the desired polymorphism in your code.

Peter - Reinstate Monica
  • 15,048
  • 4
  • 37
  • 62