Library Proposal: Reflection for C++

classic Classic list List threaded Threaded
47 messages Options
123
Reply | Threaded
Open this post in threaded view
|

Library Proposal: Reflection for C++

Stefan Roiser
Hi,

We would like to propose a library and tools which enhance C++ with  
reflection capabilities. The package, "Reflex", provides a library  
for runtime introspection and interaction with C++ "constructs" such  
as objects, types, scopes, members, templated types, ... The library  
has no external dependencies and was developed with the ISO/IEC  
standard for C++ as guideline.

Production of dictionary information of arbitrary C++ definitions is  
done via a Python script (genreflex), in a non-intrusive way, using  
an external tool (gccxml - www.gccxml.org). The generated dictionary  
source code can be compiled into a shared library, dynamically loaded  
and accessed via an API providing the introspection information.

You can find more information at

http://cern.ch/reflex

Below you may find an example code snippet which exposes a subset of  
the functionality. The four different parts show
1 - the definition of the example classes
2 - how to generate the dictionary information
3 - example on introspection (re-generate classes from the dictionary  
information)
4 - examples on interaction (get/set data members, invoke functions,  
con/destruct objects)

Cheers

     Stefan


//
// 1. original class Foo.h
//

namespace zot {

   struct foo_base {
   public:
     foo_base() : fBar(4711) {}
     ~foo_base() {}
   protected:
     int fBar;
   };

   class foo : public foo_base {
   public:
     int bar();
     void set_bar(int i);
     void set_bar(float f);
     void operator ++ ();
   };

   inline int foo::bar()             { return fBar; }
   inline void foo::set_bar(float f) { fBar = int(f); }
   inline void foo::set_bar(int i)   { fBar = i; }
   inline void foo::operator ++ ()   { ++fBar; }

} // namespace zot

//
// 2. Run python script on Foo.h generating dictionary source code
//    (Foo_rflx.cpp) and produce a shared library libFooRflx.so
//

genreflex Foo.h --gccxmlpath=/dir/to/gccxml/bin
(e.g.) g++ -shared -o libFooRflx.so Foo_rflx.cpp -I${REFLEXROOT}/
include -L${REFLEXROOT}/lib -lReflex

//
// 3. + 4. example code for introspection and interaction
//

#include "Reflex/Reflex.h"

using namespace std;
using namespace ROOT::Reflex;
enum Visibility { Public, Protected, Private };

void generate_class_decl( const Type & cl,
                           const string & indent ) {

   // ... base class declarations
   if ( cl.BaseSize()) {
     for ( Base_Iterator b = cl.Base_Begin(); b != cl.Base_End(); ++b)
       generate_class_decl((*b).ToType(), indent);
   }

   cout << indent << "class " << cl.Name();

   // ... bases
   if ( cl.BaseSize()) {

     cout << " : " ;

     for ( Base_Iterator b = cl.Base_Begin(); b != cl.Base_End(); +
+b ) {

       if ( (*b).IsVirtual() )   cout << "virtual ";
       if ( (*b).IsPublic() )    cout << "public ";
       if ( (*b).IsProtected() ) cout << "protected ";
       if ( (*b).IsPrivate() )   cout << "private ";

       cout << (*b).ToType().Name(SCOPED);

       if ( b != cl.Base_End()-1 ) cout << ", ";
     }
   }

   cout << " {" << endl;

   Visibility vis = Private;

   // ... function members
   for ( Member_Iterator f = cl.FunctionMember_Begin(); f !=  
cl.FunctionMember_End(); ++f ) {

     if ( ! (*f).IsArtificial()) {

       if ( (*f).IsPublic() && vis != Public ) {
         cout << indent << "public:" << endl;
         vis = Public;
       }
       else if ( (*f).IsProtected() && vis != Protected ) {
         cout << indent << "protected:" << endl;
         vis = Protected;
       }
       else if ( (*f).IsPrivate()   && vis != Private ) {
         cout << indent << "private:" << endl;
         vis = Private;
       }

       Type ft = (*f).TypeOf();

       cout << indent + "  ";

       if ( ! (*f).IsConstructor() && !(*f).IsDestructor() )
         cout << ft.ReturnType().Name(SCOPED) << " ";

       if (  (*f).IsOperator() ) cout << "operator ";
       cout << (*f).Name() << " (";

       if ( ft.FunctionParameterSize() ) {
         for ( size_t p = 0 ; p < ft.FunctionParameterSize(); p++ ) {
           cout << ft.FunctionParameterAt(p).Name(SCOPED|QUALIFIED);

           if ( (*f).FunctionParameterNameAt(p).length() )
             cout << " " << (*f).FunctionParameterNameAt(p);

           if ( (*f).FunctionParameterDefaultAt(p).length() )
             cout << " = " << (*f).FunctionParameterDefaultAt(p);

           if ( p != ft.FunctionParameterSize()-1 ) cout << ", ";
         }
       }
       cout << ");" << endl;
     }
   }

   // ... data members
   for ( Member_Iterator d = cl.DataMember_Begin(); d !=  
cl.DataMember_End(); ++d ) {

     if ( (*d).IsPublic() && vis != Public ) {
       cout << indent << "public:" << endl;
       vis = Public;
     }
     else if ( (*d).IsProtected() && vis != Protected ) {
       cout << indent << "protected:" << endl;
       vis = Protected;
     }
     else if ( (*d).IsPrivate()   && vis != Private ) {
       cout << indent << "private:" << endl;
       vis = Private;
     }
     cout << indent + "  " << (*d).TypeOf().Name(SCOPED)
          << " " << (*d).Name() << ";"  << endl;
   }
   cout << indent << "};" << endl;
}

void generate_class(const Type & ty) {

   string indent = "";
   Scope sc = ty.DeclaringScope();

   // ... declaring scope
   if ( ! sc.IsTopScope() ) {
     if (sc.IsNamespace())  cout << "namespace ";
     else if (sc.IsClass()) cout << "class ";

     cout << sc.Name() << " {" << endl;
     indent += "  ";
   }

   generate_class_decl(ty, indent);

   if ( ! sc.IsTopScope() ) {
     cout << "}" << endl;
     if (sc.IsClass()) cout << ";";
   }
}


int main() {

   // load the dictionary information
   void * v = dlopen("libFooRflx.so", RTLD_LAZY);


   // get meta information of type Foo
   Type fooType = Type::ByName("zot::foo");

   // check if the type is valid
   if (fooType) {

     //
     // 3. Introspection
     //

     // generate declarations for foo
     generate_class(fooType);

     //
     // 4. Interaction
     //

     // update the information for inherited members of class foo
     // this will be automatic in the future
     fooType.UpdateMembers();

     // construct an object of type Foo
     Object fooObj = fooType.Construct();

     // get the value of the data member (i.e. 4711)
     int val = Object_Cast<int>(fooObj.Get("fBar"));

     // set the data member to 4712
     fooObj.Set("fBar",++val);
     // get the data member again (i.e. 4712)
     val = Object_Cast<int>(fooObj.Get("fBar"));

     // call function setBar with value 4713
     fooObj.Invoke("set_bar",Type::ByName("void (int)"), ++val);
     // call operator ++ to increase fBar by one
     fooObj.Invoke("operator++");
     // call bar getter and cast the output to int (i.e. 4714)
     val = Object_Cast<int>(fooObj.Invoke("bar"));

     // delete the Foo object
     fooObj.Destruct();
   }

   return 0;

}

/*
//
// the output of the introspection part is
//

namespace zot {
   class foo_base {
   public:
     foo_base ();
     ~foo_base ();
   protected:
     int fBar;
   };
   class foo : public zot::foo_base {
   public:
     int bar ();
     void set_bar (int i);
     void set_bar (float f);
     void operator operator++ ();
   };
}

//
//
//
*/

--
Stefan Roiser
CERN, PH Department
CH - 1211 Geneva 23
Mob:+41 76 487 5334
Tel:+41 22 767 4838
Fax:+41 22 767 9425

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Library Proposal: Reflection for C++

Edward Diener
Stefan Roiser wrote:

> Hi,
>
> We would like to propose a library and tools which enhance C++ with  
> reflection capabilities. The package, "Reflex", provides a library  
> for runtime introspection and interaction with C++ "constructs" such  
> as objects, types, scopes, members, templated types, ... The library  
> has no external dependencies and was developed with the ISO/IEC  
> standard for C++ as guideline.
>
> Production of dictionary information of arbitrary C++ definitions is  
> done via a Python script (genreflex), in a non-intrusive way, using  
> an external tool (gccxml - www.gccxml.org). The generated dictionary  
> source code can be compiled into a shared library, dynamically loaded  
> and accessed via an API providing the introspection information.
>
> You can find more information at
>
> http://cern.ch/reflex

You need to provide an easy way in which this library can be built and
used at least under Linux and Windows. I have found the information on
this sight totally deficient in regards to creating a working version
under Windows. Your library may be excellent but unless you allow
everyone to see if it is so or not, it is not a viable alternative for
all end-users.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Library Proposal: Reflection for C++

David Abrahams
In reply to this post by Stefan Roiser
Stefan Roiser <[hidden email]> writes:

> Hi,
>
> We would like to propose a library and tools which enhance C++ with  
> reflection capabilities. The package, "Reflex", provides a library  
> for runtime introspection and interaction with C++ "constructs" such  
> as objects, types, scopes, members, templated types, ... The library  
> has no external dependencies and was developed with the ISO/IEC  
> standard for C++ as guideline.
>
> Production of dictionary information of arbitrary C++ definitions is  
> done via a Python script (genreflex), in a non-intrusive way, using  
> an external tool (gccxml - www.gccxml.org). The generated dictionary  
> source code can be compiled into a shared library, dynamically loaded  
> and accessed via an API providing the introspection information.
>
> You can find more information at
>
> http://cern.ch/reflex
>
> Below you may find an example code snippet which exposes a subset of  
> the functionality. The four different parts show
> 1 - the definition of the example classes
> 2 - how to generate the dictionary information
> 3 - example on introspection (re-generate classes from the dictionary  
> information)
> 4 - examples on interaction (get/set data members, invoke functions,  
> con/destruct objects)

How does this work relate or compare to
http://www.language-binding.net/pygccxml/pygccxml.html?

The latter already has some traction in the Boost community because of
its use in http://www.language-binding.net/pyplusplus/pyplusplus.html

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Library Proposal: Reflection for C++

pongba
In reply to this post by Stefan Roiser
Stefan Roiser <stefan.roiser <at> cern.ch> writes:

>
> Hi,
>
> We would like to propose a library and tools which enhance C++ with  
> reflection capabilities. The package, "Reflex", provides a library  
> for runtime introspection and interaction with C++ "constructs" such  
> as objects, types, scopes, members, templated types, ... The library  
> has no external dependencies and was developed with the ISO/IEC  
> standard for C++ as guideline.
>

It sounds pretty interesting:)
I extremely hoped that C++ would have reflection at, maybe, C++0x or so.
So I wish your library can make its way into boost, and, finally, into C++
standard  library.

BTW, to me, it seems the user-interface of the library needs some further
refinement though, and there's quite a lack of documents.

Regards.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Library Proposal: Reflection for C++

Stefan Roiser
In reply to this post by Edward Diener
Edward Diener <eddielee <at> tropicsoft.com> writes:

>
> Stefan Roiser wrote:
> >
> > You can find more information at
> >
> > http://cern.ch/reflex
>
[...]
> I have found the information on
> this sight totally deficient in regards to creating a working version
> under Windows. Your library may be excellent but unless you allow
> everyone to see if it is so or not, it is not a viable alternative for
> all end-users.

For the *nix world the library and tools should be buildable with the
attached autotools. For windows I will upload a VC71 solutions file to
the web page.

You may try to build it on your own. There are no external dependencies
so compiling every .cxx file in src and linking it to a dll should be enough

Cheers

Stefan

>
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
>
>




_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Library Proposal: Reflection for C++

Stefan Roiser
In reply to this post by David Abrahams
David Abrahams <dave <at> boost-consulting.com> writes:

>
> Stefan Roiser <stefan.roiser <at> cern.ch> writes:
>
> > Hi,
> >
> > We would like to propose a library and tools which enhance C++ with  
> > reflection capabilities. The package, "Reflex", provides a library  
> > for runtime introspection and interaction with C++ "constructs" such  
> > as objects, types, scopes, members, templated types, ... The library  
> > has no external dependencies and was developed with the ISO/IEC  
> > standard for C++ as guideline.
> >
> > Production of dictionary information of arbitrary C++ definitions is  
> > done via a Python script (genreflex), in a non-intrusive way, using  
> > an external tool (gccxml - www.gccxml.org). The generated dictionary  
> > source code can be compiled into a shared library, dynamically loaded  
> > and accessed via an API providing the introspection information.
> >
> > You can find more information at
> >
> > http://cern.ch/reflex
> >
> > Below you may find an example code snippet which exposes a subset of  
> > the functionality. The four different parts show
> > 1 - the definition of the example classes
> > 2 - how to generate the dictionary information
> > 3 - example on introspection (re-generate classes from the dictionary  
> > information)
> > 4 - examples on interaction (get/set data members, invoke functions,  
> > con/destruct objects)
>
> How does this work relate or compare to
> http://www.language-binding.net/pygccxml/pygccxml.html?
>
> The latter already has some traction in the Boost community because of
> its use in http://www.language-binding.net/pyplusplus/pyplusplus.html
>

I had already an off-list discussion with the developers of pygccxml. I have
been using it for private scripts and found it very useful.

The Reflex package provides a python script (genreflex.py) which produces
dictionary source code for C++ definitions. In order to do this it invokes
gccxml on these definitions and parses it's output. At the moment
genreflex.py uses it's own data structures. In the future it could be useful
to switch to pygccxml. Unfortunately at the moment we don't have the
manpower to do this.

Cheers

    Stefan


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Library Proposal: Reflection for C++

Stefan Roiser
In reply to this post by pongba
pongba <pongba <at> gmail.com> writes:

>
> Stefan Roiser <stefan.roiser <at> cern.ch> writes:
>
> >
> > We would like to propose a library and tools which enhance C++ with  
> > reflection capabilities. The package, "Reflex", provides a library  
> > for runtime introspection and interaction with C++ "constructs" such  
> > as objects, types, scopes, members, templated types, ...
>
> It sounds pretty interesting:)
> I extremely hoped that C++ would have reflection at, maybe, C++0x or so.
> So I wish your library can make its way into boost, and, finally, into C++
> standard  library.
>
> BTW, to me, it seems the user-interface of the library needs some further
> refinement though, and there's quite a lack of documents.
>

Thx, I will be very interested to receive comments on the library. There are some
examples on the web-page to give a look and feel of how it works. I have added
doxygen documentation for the API classes at

http://seal.web.cern.ch/seal/documents/dictionary/reflex/doxygen/html/index.html


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Library Proposal: Reflection for C++

Stefan Seefeld
In reply to this post by Stefan Roiser
Stefan Roiser wrote:

> Hi,
>
> We would like to propose a library and tools which enhance C++ with  
> reflection capabilities. The package, "Reflex", provides a library  
> for runtime introspection and interaction with C++ "constructs" such  
> as objects, types, scopes, members, templated types, ... The library  
> has no external dependencies and was developed with the ISO/IEC  
> standard for C++ as guideline.
>
> Production of dictionary information of arbitrary C++ definitions is  
> done via a Python script (genreflex), in a non-intrusive way, using  
> an external tool (gccxml - www.gccxml.org). The generated dictionary  
> source code can be compiled into a shared library, dynamically loaded  
> and accessed via an API providing the introspection information.

How does this compare to OpenC++ (http://opencxx.sf.net) ?

Also, have you looked into synopsis (http://synopsis.fresco.org) ? It
started by using the OpenC++ parser and infrastructure, but has been
largely rewritten since then.

Regards,
                Stefan
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Library Proposal: Reflection for C++

Edward Diener
In reply to this post by Stefan Roiser
Stefan Roiser wrote:

> Edward Diener <eddielee <at> tropicsoft.com> writes:
>
>> Stefan Roiser wrote:
>>> You can find more information at
>>>
>>> http://cern.ch/reflex
> [...]
>> I have found the information on
>> this sight totally deficient in regards to creating a working version
>> under Windows. Your library may be excellent but unless you allow
>> everyone to see if it is so or not, it is not a viable alternative for
>> all end-users.
>
> For the *nix world the library and tools should be buildable with the
> attached autotools. For windows I will upload a VC71 solutions file to
> the web page.

I look forward to seeing this for Windows.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Library Proposal: Reflection for C++

Stefan Roiser
In reply to this post by Stefan Seefeld

On 30 Jan 2006, at 15:03, Stefan Seefeld wrote:

> Stefan Roiser wrote:
>> Hi,
>>
>> We would like to propose a library and tools which enhance C++ with
>> reflection capabilities. The package, "Reflex", provides a library
>> for runtime introspection and interaction with C++ "constructs" such
>> as objects, types, scopes, members, templated types, ... The library
>> has no external dependencies and was developed with the ISO/IEC
>> standard for C++ as guideline.
>>
>> Production of dictionary information of arbitrary C++ definitions is
>> done via a Python script (genreflex), in a non-intrusive way, using
>> an external tool (gccxml - www.gccxml.org). The generated dictionary
>> source code can be compiled into a shared library, dynamically loaded
>> and accessed via an API providing the introspection information.
>
> How does this compare to OpenC++ (http://opencxx.sf.net) ?
>
> Also, have you looked into synopsis (http://synopsis.fresco.org) ? It
> started by using the OpenC++ parser and infrastructure, but has been
> largely rewritten since then.

I was not aware of synopsis. Both projects are very interesting but  
their scope seems to be different. I understood that both use  
reflection as a vehicle for their needs while Reflex only  
concentrates on introspection and interaction with C++. Reflex does  
also not try to parse C++ definitions itself but leaves this to  
gccxml (a frontend of gcc) and subsequently processes it's xml output  
to produce dictionary source code. My guess is, that it is very hard  
to implement a C++ parser. So with Reflex the dictionary information  
for any C++ definition which is compilable with gcc, can be produced.  
What may also be important is, that reflection source code is  
produced in a non-intrusive way and that interaction with objects  
from the meta-level is possible.

Cheers

        Stefan


--
Stefan Roiser
CERN, PH Department
CH - 1211 Geneva 23
Mob:+41 76 487 5334
Tel:+41 22 767 4838
Fax:+41 22 767 9425


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Library Proposal: Reflection for C++

Stefan Seefeld
Stefan Roiser wrote:

> I was not aware of synopsis. Both projects are very interesting but  
> their scope seems to be different. I understood that both use  
> reflection as a vehicle for their needs while Reflex only  
> concentrates on introspection and interaction with C++.

Synopsis is meant to be a code-source introspection framework
(with the first application being a documentation tool). From
what I understand it has about the same scope as Reflex.

> Reflex does  
> also not try to parse C++ definitions itself but leaves this to  
> gccxml (a frontend of gcc) and subsequently processes it's xml output  
> to produce dictionary source code. My guess is, that it is very hard  
> to implement a C++ parser. So with Reflex the dictionary information  
> for any C++ definition which is compilable with gcc, can be produced.  

Right, though gccxml has some drawbacks, too.

> What may also be important is, that reflection source code is  
> produced in a non-intrusive way and that interaction with objects  
> from the meta-level is possible.

That is true for synopsis, too.

FWIW,
                Stefan

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Library Proposal: Reflection for C++

Stefan Roiser

On 30 Jan 2006, at 17:08, Stefan Seefeld wrote:

>> Reflex does
>> also not try to parse C++ definitions itself but leaves this to
>> gccxml (a frontend of gcc) and subsequently processes it's xml output
>> to produce dictionary source code. My guess is, that it is very hard
>> to implement a C++ parser. So with Reflex the dictionary information
>> for any C++ definition which is compilable with gcc, can be produced.
>
> Right, though gccxml has some drawbacks, too.

We have fortunately not found problems yet and we generated  
dictionaries for a lot of user code in our environment and also  
"external" libraries. These dictionaries are then e.g. further used  
for persistence of objects.

>
>> What may also be important is, that reflection source code is
>> produced in a non-intrusive way and that interaction with objects
>> from the meta-level is possible.
>
> That is true for synopsis, too.

With interaction with objects I meant e.g. through the meta-level  
instantiate a class, get/set the data member values, call a function  
on that instance, retrieve the function's return value and so on. I  
may have missed that, but I couldn't find examples on the synopsis  
page for this functionality.

Reflex code for this would look something like

Type t = Type::ByName("foo");
Object instance = t.Construct();
Object ret_obj = instance.Invoke("myFunction");

Cheers

        Stefan

--
Stefan Roiser
CERN, PH Department
CH - 1211 Geneva 23
Mob:+41 76 487 5334
Tel:+41 22 767 4838
Fax:+41 22 767 9425


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Library Proposal: Reflection for C++

Stefan Seefeld
Stefan Roiser wrote:

>>>What may also be important is, that reflection source code is
>>>produced in a non-intrusive way and that interaction with objects
>>>from the meta-level is possible.
>>
>>That is true for synopsis, too.
>
>
> With interaction with objects I meant e.g. through the meta-level  
> instantiate a class, get/set the data member values, call a function  
> on that instance, retrieve the function's return value and so on. I  
> may have missed that, but I couldn't find examples on the synopsis  
> page for this functionality.

You are right, that's not possible. I was thinking of interactions
with the objects representing the parse tree, syntax tree, symbol table,
etc.
Interacting with the running code may involve quite a bit of work
that, at least when taken in its most general form, requires knowledge
that a parser (or compiler frontend) can not have just from introspecting
the code.
Synopsis provides C++ and python interfaces to the internal representations,
and so my hope is that higher level tools, even ones that compile and load
the introspected code, can easily be built (e.g. scripted) with them.

> Reflex code for this would look something like
>
> Type t = Type::ByName("foo");
> Object instance = t.Construct();

That clearly only works if 'foo' has a default constructor, right ?
Even then, it may involve some other resources to be set up. So, what
knowledge of the code being invoked that way do you require ? Who
would provide the implementation for 'foo', who would provide
the above lines, and who would finally execute them ?

> Object ret_obj = instance.Invoke("myFunction");

Regards,
                Stefan
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Library Proposal: Reflection for C++

Stefan Roiser

On 30 Jan 2006, at 23:55, Stefan Seefeld wrote:

> Stefan Roiser wrote:
>
>
>> Reflex code for this would look something like
>>
>> Type t = Type::ByName("foo");
>> Object instance = t.Construct();
>
> That clearly only works if 'foo' has a default constructor, right ?

You are right, the above code snippet has a lot of assumptions (e.g.  
we found a dictionary for type foo, foo has a default constructor  
etc.), please see below for a bit more safe implementation.

> Even then, it may involve some other resources to be set up. So, what
> knowledge of the code being invoked that way do you require ?

Reflex would need a dictionary for class "foo" (generated by  
genreflex.py with gccxml). So something like

      python genreflex.py foo.h --gccxmlpath=/path/to/gccxml/bin

will generate a file foo_rflx.cpp with the dictionary information  
about class foo.
This file will contain all the information necessary to introspect/
interact with foo
and can be compiled into a shared library libfoo.so

> Who
> would provide the implementation for 'foo', who would provide
> the above lines, and who would finally execute them ?

I'm assuming that class foo is a class for which the dictionary is  
generated and subsequently a user want's to introspect/interact with  
its dictionary information.



So a bit more safe implementation of the lines above would be

// load dynamically library libfoo.so

Type t = Type::ByName("foo");

if (t && t.IsClass()) {

   // we found the dictionary information for "foo" and it's a class

   // let's try to call the default constructor
   // Construct has several default arguments, by default it will try  
to invoke the default constructor
   Object instance = t.Construct();

   if (instance) {

     // we have a valid instance (memory allocated, type associated)
     // we have constructed an instance through the default constructor

   }
   else {

     // this class does not have a default constructor
     // let's loop over all constructors and look for one which takes  
e.g. one int as argument

     for (Member_iterator mi = t.FunctionMember_Begin(); mi !=  
t.FunctionMember_End(); ++mi) {

       if ((*mi).IsConstructor()) {

        Type constType = (*mi).TypeOf();
         if (constType.FunctionParameterSize() == 1 &&  
constType.FunctionParameterAt(0).TypeOf().Name() == "int") {

            // let's invoke this constructor with one argument (this  
has to be passed in a vector<void*>)
            int arg0 = 111;
            std::vector<void*> args;
            args.push_back(&arg0);
            instance = t.Construct(constType,args);

            .......



Cheers

        Stefan


--
Stefan Roiser
CERN, PH Department
CH - 1211 Geneva 23
Mob:+41 76 487 5334
Tel:+41 22 767 4838
Fax:+41 22 767 9425


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Library Proposal: Reflection for C++

Stefan Roiser
In reply to this post by Edward Diener

On 30 Jan 2006, at 16:13, Edward Diener wrote:

> Stefan Roiser wrote:
>> Edward Diener <eddielee <at> tropicsoft.com> writes:
>>
>>> Stefan Roiser wrote:
>>>> You can find more information at
>>>>
>>>> http://cern.ch/reflex
>> [...]
>>> I have found the information on
>>> this sight totally deficient in regards to creating a working  
>>> version
>>> under Windows. Your library may be excellent but unless you allow
>>> everyone to see if it is so or not, it is not a viable  
>>> alternative for
>>> all end-users.
>>
>> For the *nix world the library and tools should be buildable with the
>> attached autotools. For windows I will upload a VC71 solutions  
>> file to
>> the web page.
>
> I look forward to seeing this for Windows.
>

I have uploaded a VC71 project solution file to the web page at

http://seal-reflex.web.cern.ch/seal-reflex/releases.html

This should build a Reflex.dll. Sorry for the delay but I first had  
to find a way how to export the symbols (this is done with our build  
tools by default). The solution now is to export every symbol. This  
is too much and I probably should do something similar like boost  
choosing the proper set of symbols with the decl_export/import for  
windows.

To produce dictionary sources you will need to do

python python/genreflex/genreflex.py MyHeader.h --gccxmlpath=c:/my/
path/to/gccxml/bin

and then compile the resulting MyHeader_rflx.cpp into a shareable  
library and dynamically load it into your application (no symbols  
need to be exported).

If you discover problems please let me know.

Cheers

        Stefan

--
Stefan Roiser
CERN, PH Department
CH - 1211 Geneva 23
Mob:+41 76 487 5334
Tel:+41 22 767 4838
Fax:+41 22 767 9425


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Library Proposal: Reflection for C++

pongba
In reply to this post by Stefan Roiser
Stefan Roiser <stefan.roiser <at> cern.ch> writes:

>
>
> On 30 Jan 2006, at 23:55, Stefan Seefeld wrote:
>
> > Stefan Roiser wrote:
> >
> >
> >> Reflex code for this would look something like
> >>
> >> Type t = Type::ByName("foo");
> >> Object instance = t.Construct();
> >
> > That clearly only works if 'foo' has a default constructor, right ?

Just so you know, I'm strongly wondering if you could implement a serialization
library(e.g. boost::serialization) using Reflex. No doubt it should have that
capability. Not only would this be a good example that illustrates the power of
your framework, it would contribute a much-easier-to-use serialization library
as well, considering that boost::serialization is a little inconvenient to use.

Regards.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Library Proposal: Reflection for C++

David Abrahams
In reply to this post by Stefan Roiser
Stefan Roiser <[hidden email]> writes:

> On 30 Jan 2006, at 17:08, Stefan Seefeld wrote:
>
> With interaction with objects I meant e.g. through the meta-level  
> instantiate a class, get/set the data member values, call a function  
> on that instance, retrieve the function's return value and so on. I  
> may have missed that, but I couldn't find examples on the synopsis  
> page for this functionality.
>
> Reflex code for this would look something like
>
> Type t = Type::ByName("foo");
> Object instance = t.Construct();
> Object ret_obj = instance.Invoke("myFunction");

Very interesting.  Where do you get the object code for
foo::myFunction?  Or have you implemented a full C++ interpreter?

Have you considered something like the object interface of
Boost.Python?

  Type t = Type::ByName("foo"):
  Object instance = t();
  Object ret_obj = instance.member("myFunction")();

Then you'd also have, e.g.

  Object enlarged = instance & 5;

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Library Proposal: Reflection for C++

Stefan Roiser

On 31 Jan 2006, at 19:40, David Abrahams wrote:

> Stefan Roiser <[hidden email]> writes:
>
>> On 30 Jan 2006, at 17:08, Stefan Seefeld wrote:
>>
>> With interaction with objects I meant e.g. through the meta-level
>> instantiate a class, get/set the data member values, call a function
>> on that instance, retrieve the function's return value and so on. I
>> may have missed that, but I couldn't find examples on the synopsis
>> page for this functionality.
>>
>> Reflex code for this would look something like
>>
>> Type t = Type::ByName("foo");
>> Object instance = t.Construct();
>> Object ret_obj = instance.Invoke("myFunction");
>
> Very interesting.  Where do you get the object code for
> foo::myFunction?  Or have you implemented a full C++ interpreter?

foo::myFunction will be invoked through a stub function which is part  
of the dictionary library for class foo. A dictionary library may be  
dynamically loaded in a program.

The source code for this dictionary library is produced in a non-
intrusive way with a python script (genreflex.py). Besides the stub  
functions this dictionary source code contains the information about  
all types, scopes, members one wants to generate the reflection  
information for.

To give you an idea, typically this automatically produced code would  
look like (this is part of the code for the example class of my first  
mail)

static void* constructor_3558( void* mem, const std::vector<void*>&  
arg, void*) {
   return ::new(mem) ::zot::foo(*(const ::zot::foo*)arg[0]);
}
static void* constructor_3559( void* mem, const std::vector<void*>&,  
void*) {
   return ::new(mem) ::zot::foo();
}
static void* destructor_3560(void * o, const std::vector<void*>&,  
void *) {
   ((::zot::foo*)o)->~foo(); return 0;
}
static void* method_3561( void* o, const std::vector<void*>&, void*)
{
   static int ret;
   ret = ((::zot::foo*)o)->bar();
   return &ret;
}
......

void __zot__foo_dict() {
   ClassBuilder("zot::foo", typeid(zot::foo), sizeof(zot::foo),  
PUBLIC | CLASS)
   .AddBase(type_2263, BaseOffset< ::zot::foo, ::zot::foo_base >::Get
(), VIRTUAL | PUBLIC)
   .AddFunctionMember(FunctionTypeBuilder(type_void, type_4260),  
"foo", constructor_3558, 0, "_ctor_arg", PUBLIC | ARTIFICIAL |  
CONSTRUCTOR)
   .AddFunctionMember(FunctionTypeBuilder(type_void), "foo",  
constructor_3559, 0, 0, PUBLIC | ARTIFICIAL | CONSTRUCTOR)
   .AddFunctionMember(FunctionTypeBuilder(type_void), "~foo",  
destructor_3560, 0, 0, PUBLIC | ARTIFICIAL | DESTRUCTOR )
   .AddFunctionMember(FunctionTypeBuilder(type_9), "bar",  
method_3561, 0, 0, PUBLIC)
   ......

>
> Have you considered something like the object interface of
> Boost.Python?
>
>   Type t = Type::ByName("foo"):
>   Object instance = t();
>   Object ret_obj = instance.member("myFunction")();
>
> Then you'd also have, e.g.
>
>   Object enlarged = instance & 5;

To be frank - no, but this is a very good idea. Thx for the input!

>
> --
> Dave Abrahams
> Boost Consulting
> www.boost-consulting.com
>
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman/ 
> listinfo.cgi/boost

--
Stefan Roiser
CERN, PH Department
CH - 1211 Geneva 23
Mob:+41 76 487 5334
Tel:+41 22 767 4838
Fax:+41 22 767 9425


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Library Proposal: Reflection for C++

Ion Gaztañaga
  > foo::myFunction will be invoked through a stub function which is part
> of the dictionary library for class foo. A dictionary library may be  
> dynamically loaded in a program.
>
> The source code for this dictionary library is produced in a non-
> intrusive way with a python script (genreflex.py). Besides the stub  
> functions this dictionary source code contains the information about  
> all types, scopes, members one wants to generate the reflection  
> information for.

This sounds similar to another CERN project: Cint
(http://root.cern.ch/root/Cint.html), the C/C++ interpreter. Do they
share code? This reflection method seems interesting (although a native
one would be better no doubt). In addition to your library I would
encourage Cint guys to present the library to Boost (for example, they
could use the Wave preprocessor for complex C/C++ instead of writing
their own). A C/C++ interpreter would be killer for Boost (having also
native<->interpreted transitions).

Regards,

Ion




_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Library Proposal: Reflection for C++

Stefan Roiser
In reply to this post by pongba

On 31 Jan 2006, at 15:44, pongba wrote:

> Stefan Roiser <stefan.roiser <at> cern.ch> writes:
>
>>
>>
>> On 30 Jan 2006, at 23:55, Stefan Seefeld wrote:
>>
>>> Stefan Roiser wrote:
>>>
>>>
>>>> Reflex code for this would look something like
>>>>
>>>> Type t = Type::ByName("foo");
>>>> Object instance = t.Construct();
>>>
>>> That clearly only works if 'foo' has a default constructor, right ?
>
> Just so you know, I'm strongly wondering if you could implement a  
> serialization
> library(e.g. boost::serialization) using Reflex. No doubt it should  
> have that
> capability. Not only would this be a good example that illustrates  
> the power of
> your framework, it would contribute a much-easier-to-use  
> serialization library
> as well, considering that boost::serialization is a little  
> inconvenient to use.

I will be very happy if boost::serialization shows interest in Reflex.

But in fact such projects already exist at CERN :-)

- The POOL project does persistence of C++ objects and uses Reflex  
for this purpose. You may have a look at http://pool.cern.ch/ for  
details.

- The ROOT project, among other things, also does persistence of C++  
objects. We are currently working on changing the underlying  
reflection system for ROOT to switch to Reflex. More infos at http://
root.cern.ch


--
Stefan Roiser
CERN, PH Department
CH - 1211 Geneva 23
Mob:+41 76 487 5334
Tel:+41 22 767 4838
Fax:+41 22 767 9425


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
123