Examples
The user API of the Reflex consists of 8 classes which provide
the full functionality of the package:
- Type
- Scope
- Member
- Object
- Template
- PropertyList
- MemberTemplate
- TypeTemplate
For the examples we will use the class below
class MyClass {
public:
MyClass();
MyClass(int val);
virtual ~MyClass();
int val() const;
void setVal(int val);
private:
int m_val;
};
- LOOKUP: The first thing is to enter the model. This
can be done through the static function "byName(std::string)"
which is a member of the "Type", "Scope" and
"Template" class. Below is an example of how to look
up a Type.
Type t = Type::ByName("MyClass");
- TYPES: All the API types have an operator bool() which
will return true if the Type/Scope/etc that was retrieved is valid.
Furthermore one may investigate which kind of Type was retrieved
(it could be also a Pointer, Function, Array, etc.)
if ( t ) {
if ( t.IsClass()) std::cout << "We found a class type" << std::endl;
if (t.TypeType() == CLASS) std::cout << "This is still a class" << std::endl;
}
- INSTANCES: Once a an allocatable type is retrieved
it is possible to allocate/deallocate the memory for this type
or to construct/destruct it
void * v = t.Allocate();
t.Destruct(v); Object o = t.Construct();
- MEMBERS: In case of the class we found a "special"
type which is both a type and a scope at the same time. As scopes
can have members we can now iterate over the members and investigate
their types, names etc.
for (Member_Iterator mi = t.Member_Begin(); mi != t.Member_End(); ++mi) {
switch ((*mi).MemberType()) {
case DATAMEMBER : std::cout << "Datamember: " << (*mi).Name() << " at offset " << (*mi).Offset() << std::endl;
case FUNCTIONMEMBER : std::cout << "Functionmember: " << (*mi).Name() << " has " << (*mi).FunctionParameterSize() << " parameters " << std::endl;
default : std::cout << "This should never happen" << std::endl;
}
}
- MEMBER INTERACTION: One can also interact with the
members of a scope if one holds an instance of this class. Using
the object we constructed above we can get and set the values
of the data members and also invoke the function members of the
class
Member dm = t.DataMemberAt(0);
std::cout << "Data member " << dm.Name() << " is of type " << dm.TypeOf().Name() << std::endl;
int i = Object_Cast<int>(dm.Get(o));
++i;
dm.Set(o,&i);
Member fm = t.FunctionMemberAt(0);
if (fm.TypeOf().ReturnType().Name() != "void" && fm.FunctionParameterSize() == 0) Object o = fm.Invoke(o);
- SCOPES: The second entry to the model is through the
Scopes. The Scope class also has a byName(std::string) function
which allows the lookup of a certain scope (the argument must
be the fully qualified name of the scope). Once a scope was retrieved
one may go up and down in the scope hierarchy and investigate
the members of the scope.
Scope s = Scope::ByName("MyClass");
if ( s.DeclaringScope().IsTopScope()) {
std::cout << "Scope " << s.Name() << " is part of the top scope and has "
<< s.SubScopeSize() << " sub scopes " << std::endl;
}
- PROPERTYLIST: Types, Scopes and Member can have a PropertyList
attached to them. The idea of the PropertyList is to store all
"extra" information in form of key/value pairs which
is not part of the C++ standard (examples could be a description,
a class ID or an author name). The keys of the PropertyList are
strings while the values are objects of a type Any (included from
Boost::Any) which can hold any arbitrary information the user
wants (e.g. strings, objects, pointers, etc)
PropertyList p = s.Properties();
if (p.HasKey("Author")) std::cout << "The author of class " << s.Name() << " is " << p.PropertyAsString("Author") << std::endl;
- TEMPLATE: Templates will be supported inherently by
the model. Nevertheless this part is still under development and
bound to change in the near future. For this reason no example
code is given here.
|