[GCC-XML] C++ Reflection Using GCCXML?
Bryan Ischo
bji-gccxml at ischo.com
Wed Apr 25 18:28:56 EDT 2007
CHABO Gabriel wrote:
>
> Hi,
>
> I just read your post about Reflection using GCCXML.
>
> Do you know if anyone took it upon himself to develop such a project?
>
> Also, I'm wondering about uninstantiated template support in the current
version, what I want to do is define a set of rules that govern the
coding convention of a cpp file, one of which is to forbid the use of
templates (for now), Is there any way I can do this in GCCXML?
>
> Thank you and regards,
>
> Gabriel Chabo
>
What an amazing coincidence.
Over the past week I have just been putting the finishing touches on my
project before releasing it. I was going to announce it on the gccxml
mailing list.
I'll give you a brief description here of what I'm doing:
I have implemented a project that I call "xrtti", which stands for
eXtended Runtime Type Information for C++. It uses gccxml to generate a
source file that you compile and link into your project. If you do so,
you then can reflect on any of the classes that your project defines. You
can do things like look up classes, methods, their types, etc. You can
"create" new instances of classes that you can reflect on in this way,
like this:
------
// Look up the class you are interested in
const Class *pMyClass = Xrtti::LookupClass("Foo::Bar");
if (pMyClass == NULL) {
printf("Could not find class Foo::Bar\n");
return -1;
}
// Call the Create() method to create a new instance
void *pNewInstance = pMyClass->Create();
// If it returned NULL, then "Foo::Bar" was a non-instantiable
// (i.e., abstract)
if (pNewInstance == NULL) {
printf("Could not create an instance of Foo::Bar\n");
return -1;
}
// Iterate over the list of methods available in myClass to find the
// one you want; perhaps eventually a "findMethod" utility will be
// implemented so this will be a little easier
const Xrtti::Method *pMyMethod = NULL;
int methodCount = pMyClass->GetMethodCount();
for (int i = 0; i < methodCount; i++) {
const Xrtti::Method &method = pMyClass->GetMethod(i);
if (!strcmp(method.GetName(), "SomeMethod")) {
pMyMethod = &method;
break;
}
}
if (pMyMethod == NULL) {
printf("Could not find method SomeMethod\n");
return -1;
}
// Declare the arguments array that will contain the method arguments.
// You would know how many arguments there are to the method and their
// type by reflecting on the Method
Xrtti::Value args[3];
args[0].signed_int_v = 5;
args[1].pointer_v = "Hello,world!";
args[2].float_v = 11.0;
Xrtti::Value returnValue;
// This call is equivalent to calling:
// returnValue.int_v = ((Foo::Bar *) pNewInstance->SomeMethod
// (args[0].int_v, args[1].pointer_v, args[2].float_v);
// ... assuming that the signature of SomeMethod looked like this:
// int SomeMethod(int, char *, float);
pMyMethod->Invoke(pNewInstance, returnValue, args);
printf("SomeMethod returned %d\n", returnValue.signed_int_v);
// All of the above is much less interesting than reflecting on classes
// that your runtime doesn't know about. If you know about Foo::Bar
// already, then you might as well just call its methods directly! But
// with Xrtti, you can introspect on classes that you have never heard
// of before and use them via Xrtti metaprogramming just like other C++
// classes that you do know about
------
Anyway, that's a brief introduction to what you can do. You can get
enough detail out of the Xrtti reflection system to completely re-emit the
original class definitions of most classes (I know this because one of my
test cases re-creates the header file that the test case was built from
using the Xrtti system), so every detail about most classes is present
(there are a few things which are not present, including initialization
values of static members, and some other minor things).
You can also invoke any method on any class using this "metaprogramming"
technique I demonstrated above. There are also getters/setters for every
field of every class, so you can programmatically get and set values in
classes.
I am almost done with this project and ready to release it, I just have a
couple more things to do:
- Finish my test case for getter/setter methods so that I can be sure that
it is working correctly (already finished the test case for
constructors/destructors and invoke methods)
- I have been using gccxml 6.0 the entire development cycle, I need to get
around to compiling the newest gccxml and running Xrtti with it to make
sure it works (if it doesn't, there are probably minor variations in the
XML output of gccxml that I will have to incorporate)
- Better documentation; all of my code is well documented and generates
pretty good doxygen API docs, but I would like to write some more HOWTO
and FAQ type docs.
Anyway, I am Real Close Now after having worked on this off and on for a
couple of years (much longer than it would take someone with more time and
dedication than myself!).
I would be happy to share a snapshot of Xrtti with you if you'd like to
see it. I am going to release it under GPLv2.
Also, I should have mentioned this at the beginning - while developing
Xrtti I discovered that there is already a project out there that did
something very similar. It is called "SEAL Reflex" and you can find it
at:
http://seal-reflex.web.cern.ch/seal-reflex/index.html
It looks to be complete and ready to use. However, I did not like its API
which I consider to be much more awkward than what I would like. Xrtti is
intended to have the cleanest API possible, and I personally find it much
nicer than SEAL Reflex. But this is a matter of opinion (and an obviously
biased one) so you should look at both and see if you like SEAL Reflex
better. SEAL Reflex certainly has many more methods than Xrtti; I tried
to be minimalistic and simple with Xrtti, and you may prefer the more
"complete" approach of SEAL Reflex more to your liking.
Finally, my plans after releasing Xrtti are to implement a library for
doing "serialization" of C++ objects into binary form. In fact this was
my whole goal originally, and I implemented a complete software system to
do this, which worked quite well, but then when it was done, took a step
back and said - hey, this would be even better as two separate components
- a generically useful reflection system, and then a serialization system
built on top of that. So I spent the next year and a half making the
first part happen.
I'm appending the Xrtti.h header file to a separate email so that you can
see the complete API if you are interested (I tried appending it to this
email originally and the gccxml list rejected the mail as too large).
Comments/questions are very welcome!
Thank you,
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