[GCC-XML] Xrtti.h

Bryan Ischo bji-gccxml at ischo.com
Thu Apr 26 22:43:29 EDT 2007


> Bingo.  For static arrays this obviously isn't necessary, but for
> dynamically allocated arrays, the user can specify a field which will be
> the count.

There is another troubling aspect to generating serializer functions,
which I forgot to ask you about previously.

When a method is generated to serialize an instance of a given class, and
the function which is thus generated exists outside the class definition
itself, the generated function will not have access to private member
variables of the class.

So for example if you have a class:

class Foo
{
public:

    int a;

private:

    int b;
};

Then if you generate a serializer function that looks something like this
(pseudo-code):

void SerializeFoo(const Foo *pFoo, Serializer &serializer)
{
    serializer << pFoo->a;
    serializer << pFoo->b;
}

When this code is compiled, it will fail, because the SerializeFoo
function does not have access to the private member variable Foo::b.

I can see five ways around this:

1. Require that the serialize functions thus generated be part of the
class itself; so that you require that the developer add a signature "void
Serialize(...)" to their class, and your tool just generates the method
definition to fill in "Foo::Serialize(...)".  In this way, the developer
is giving the method that you generate access to all private data members.
 The problem with this approach is that it requires that
serialize/deserialize method signatures be added to every class by the
developer.

2. Don't allow private member variables in classes to be serialized.  This
is pretty unpalatable though because it doesn't allow developers to use
access keywords to enforce encapsulation in their code.  Essentially,
developers can never use "protected" and "private" member variables.

3. Require the developer to make their "protected" and "private" member
variables conditional upon some preprocessing macro that gives access to
these members only to your generated code.  For example, require the
developer to do something like this:

class Foo
{
public:

    int a;

#ifndef SERIALIZER
private:
#endif // SERIALIZER

    int b;
};

  The above would mean that for all definitions of Foo seen by all code
that the developer writes, "b" would be private in the class above.
Only the code generated by the serializer tool would #define SERIALIZER,
and thus have access to private members.  This has the disadvantage of
making for some really, really ugly and error prone class definitions.

4. #define private public & #define protected public, in the code that is
generated by the serializer, before #including the header file that
defines the classes to be serialized.  This is a really cheesy way to
basically break the rules of C++ (I believe the C++ standard specifically
says that code is not ever supposed to do this) and "promote" the
generated code to have full access to all members of the class.

5. Have the serializer-generator also generate "proxy" classes which
mirror exactly the classes to serialize, except they define everything
public.  Thus the serializer would output a "FooProxy" class definition
that looked exactly like the "Foo" I described above, except that it would
start with public: access and never set anything private.  Then the
serializer would, to serialize a Foo, first cast it to a FooProxy, and
serialize that.

Believe it or not, my code generating tool, xrttigen, uses option (4).
It's really hacky and I have to wonder if it will work with all compilers.
 But it works great with gcc!

There is a minor caveat: you also have to #define class struct.  This is
so that you get access to private member variables of classes for which no
access was specified, and thus defaulted to private.  If you turn those
into structs (which from my understanding of C++, is exactly equivalent,
except that the default access becomes public instead of private), then
you solve this problem.  Unfortunately, when I do this, I find that some
obscure C++ header files (especially those in the C++ std library) break
in ways I don't understand.

If 4 ends up being too problematic, I think I will re-implement using 5.

Just wondering how you tackle this problem.

Thanks,
Bryan


------------------------------------------------------------------------
Bryan Ischo                bryan at ischo.com            2001 Mazda 626 GLX
Hamilton, New Zealand      http://www.ischo.com     RedHat Fedora Core 5
------------------------------------------------------------------------





More information about the gccxml mailing list