This example illustrates how python can directly access reflection information about classes, interfaces etc.
With the following C++
namespace pizza
{
$typedef+ float64 TCurrency;
$typedef+ string8 TEmail;
$typedef+ string8 TPhoneNumber;
$model+ TAddress
{
string8 Line1;
string8 Line2;
string8 Line3;
string8 Line4;
string8 City;
int32 ZipPostCode;
string8 StateProvinceCounty;
string8 Country;
};
$model+ TEmployee
{
int32 Id;
TAddress Address;
string8 Name;
TPhoneNumber Phone;
};
$model+ TVehicleType
{
int32 Id;
string8 Description;
};
$model+ TVehicle
{
int32 Id;
int32 VehicleTypeId;
};
$enum+ class EPaymentMethod
{
Cash,
EftPos,
CreditCard
};
$model+ TCustomer
{
int32 Id;
TAddress Address;
string8 Name;
TPhoneNumber Phone;
TEmail Email;
dt::TDateTime DateOfFirstOrder;
EPaymentMethod PaymentMethod;
};
$enum+ class EDeliveryStatus
{
Cooking,
Delivering,
Completed,
Returned
};
$enum+ class EBaseType
{
Thin,
DeepPan
};
$model+ TCircle
{
float32 Radius;
};
$model+ TRectangle
{
float32 Width;
float32 Height;
};
$variant+ TShape
{
default TCircle(200);
TCircle;
TRectangle;
};
$model+ TToppings
{
int32 Id;
TCurrency Price;
string8 Description; // e.g. "Ham", "Pineapple"
};
$model+ TOrderedPizza
{
TShape Shape;
EBaseType BaseType;
xvector ToppingIds;
};
$struct+ TOrder isa ceda::IPersistable :
model
{
int32 Id;
int32 CustomerId;
int32 TakenByEmployeeId;
int32 DeliveredByEmployeeId;
EDeliveryStatus DeliveryStatus;
int32 VehicleId;
dt::TDateTime DateTimeOrderTaken;
dt::TDateTime DateTimeOrderDelivered;
TCurrency TotalOrderPrice;
xvector Pizzas;
}
{
};
$interface+ IProcessOrder
{
void ProcessOrder(const TOrder& order);
int32 GetNumPendingOrders() const;
};
$struct+ TPizzaDeliveryDatabase isa ceda::IPersistable :
model
{
xvector< movable< cref > > Orders;
}
{
};
} // namespace pizza
the following Python
# python code
def PrintEnumInfo(e,indent):
print ' '*indent + '$enum ' + `e.GetName()`
print ' '*indent + '{'
for i in range(0,e.GetCount()):
str = ' '*indent + ' '
if not e.GetEnable(i):
str += '-'
str += `e.GetString(i)` + ' = ' + `e.GetValue(i)`
print str
print ' '*indent + '}'
def GetFunctionPrototype(rbcRet,getArgByteCode,isMethod,fn):
proto = ''
if rbcRet.IsNull():
proto = 'void'
else:
proto = `rbcRet`
proto += ' ' + `fn.GetName()` + '('
for j in range(0,fn.GetNumArgs().AsInt32()):
a = fn.GetArg(j)
rbc = getArgByteCode(a)
proto += `rbc` + ' ' + `a.GetName()`
if j != fn.GetNumArgs().AsInt32()-1:
proto += ','
proto += ')'
if isMethod and fn.IsConst():
proto += ' const'
return proto
# Returns a string representation of the prototype of an interface method
def GetInterfaceMethodPrototype(ri,m):
rbcRet = ceda.GetInterfaceMethodReturnTypeByteCode(ri,m)
def getArgByteCode(a):
return ceda.GetInterfaceMethodArgByteCode(ri,a)
isMethod = 1
return GetFunctionPrototype(rbcRet,getArgByteCode,isMethod,m)
# Returns a string representation of the prototype of a class method
def GetClassMethodPrototype(rc,m):
rbcRet = ceda.GetClassMethodReturnTypeByteCode(rc,m)
def getArgByteCode(a):
return ceda.GetClassMethodArgByteCode(rc,a)
isMethod = 1
return GetFunctionPrototype(rbcRet,getArgByteCode,isMethod,m)
def GetGlobalFunctionPrototype(gf):
rbcRet = ceda.GetGlobalFunctionReturnTypeByteCode(gf)
def getArgByteCode(a):
return ceda.GetGlobalFunctionArgByteCode(gf,a)
isMethod = 0
return GetFunctionPrototype(rbcRet,getArgByteCode,isMethod,gf)
def GetFunctorPrototype(f):
rbcRet = ceda.GetFunctorReturnTypeByteCode(f)
def getArgByteCode(a):
return ceda.GetFunctorArgByteCode(f,a)
isMethod = 0
return GetFunctionPrototype(rbcRet,getArgByteCode,isMethod,f)
def PrintGlobalFunctionInfo(gf,indent):
print ' '*indent + '$function ' + GetGlobalFunctionPrototype(gf)
def PrintFunctorInfo(f,indent):
print ' '*indent + '$functor ' + GetFunctorPrototype(f)
def PrintGlobalVariableInfo(gv,indent):
rbc = ceda.GetGlobalVariableByteCode(gv)
print ' '*indent + '$var ' + `rbc` + ' ' + `gv.GetName()`
def PrintTypedefInfo(t,indent):
rbc = ceda.GetTypeDefByteCode(t)
print ' '*indent + '$typedef ' + `rbc` + ' ' + `t.GetName()`
def PrintInterfaceInfo(ri,indent):
print ' '*indent + '$interface ' + `ri.GetName()`
print ' '*indent + '{'
for i in range(0,ri.GetNumMethods().AsInt32()):
m = ri.GetMethod(i)
print ' '*indent + ' ' + GetInterfaceMethodPrototype(ri,m)
print ' '*indent + '}'
def PrintVariantInfo(rv,indent):
print ' '*indent + '$variant ' + `rv.GetName()`
print ' '*indent + '{'
for i in range(0,rv.GetNumFields().AsInt32()):
f = rv.GetField(i)
rbc = ceda.GetVariantFieldByteCode(rv,f)
str = '[' + `f.GetOffset()` + ']'
str += ' '
str += `rbc` + ' ' + `f.GetName()`
print ' '*indent + ' ' + str
print ' '*indent + '}'
def GetClassSpecifier(c):
#if c.IsStruct():
#return 'datasource'
if c.IsModel():
return 'model'
elif c.IsAdt():
return 'adt'
elif c.IsStruct():
return 'struct'
else:
return 'class'
def PrintClassInfo(c,indent):
print ' '*indent + '$' + GetClassSpecifier(c) + ' ' + `c.GetName()`
print ' '*indent + '{'
indent += 4
#print ' '*indent + 'Flags = ' + `c.GetFlags()`
print ' '*indent + 'Size = ' + `c.GetSize()` + ' bytes'
print ' '*indent + 'CanCreate = ' + `c.CanCreate()`
if c.GetNumModelFields().AsInt32() > 0:
print ' '*indent + 'model'
print ' '*indent + '{'
for i in range(0,c.GetNumModelFields().AsInt32()):
f = c.GetModelField(i)
rbc = ceda.GetModelFieldByteCode(c,f)
str = '[' + `f.GetOffset()` + ']'
str += ' '
str += `rbc` + ' ' + `f.GetName()` + ' '
str += '[' + `f.GetRsn1()` + ',' + `f.GetRsn2()` + ')'
if not f.Present():
str += '*'
print ' '*indent + ' ' + str
print ' '*indent + '}'
if c.GetNumFields().AsInt32() > 0:
print ' '*indent + 'fields'
print ' '*indent + '{'
for i in range(0,c.GetNumFields().AsInt32()):
f = c.GetField(i)
rbc = ceda.GetFieldByteCode(c,f)
str = '[' + `f.GetOffset()` + ']'
str += ' '
str += `rbc` + ' ' + `f.GetName()`
print ' '*indent + ' ' + str
print ' '*indent + '}'
if c.GetNumMethods().AsInt32() > 0:
print ' '*indent + 'methods'
print ' '*indent + '{'
for i in range(0,c.GetNumMethods().AsInt32()):
m = c.GetMethod(i)
print ' '*indent + ' ' + GetClassMethodPrototype(c,m)
print ' '*indent + '}'
if c.GetNumIndirectInterfaces().AsInt32() > 0:
print ' '*indent + 'indirect interfaces'
print ' '*indent + '{'
for i in range(0,c.GetNumIndirectInterfaces().AsInt32()):
nm = c.GetInterfaceName(i)
print ' '*indent + ' ' + `nm`
print ' '*indent + '}'
if c.GetNumDirectInterfaces().AsInt32() > 0:
print ' '*indent + 'direct interfaces'
print ' '*indent + '{'
for i in range(c.GetNumIndirectInterfaces().AsInt32(),c.GetNumInterfaces().AsInt32()):
nm = c.GetInterfaceName(i)
print ' '*indent + ' ' + `nm`
print ' '*indent + '}'
indent -= 4
print ' '*indent + '}'
def PrintNameSpaceElement(nse,indent):
tp = nse.GetType()
if tp == ceda.ENSType.NST_Interface:
PrintInterfaceInfo(nse.AsInterface(),indent)
elif tp == ceda.ENSType.NST_Class:
PrintClassInfo(nse.AsClass(),indent)
elif tp == ceda.ENSType.NST_GlobalFunction:
PrintGlobalFunctionInfo(nse.AsGlobalFunction(),indent)
elif tp == ceda.ENSType.NST_GlobalVariable:
PrintGlobalVariableInfo(nse.AsGlobalVariable(),indent)
elif tp == ceda.ENSType.NST_Typedef:
PrintTypedefInfo(nse.AsTypedef(),indent)
elif tp == ceda.ENSType.NST_Enum:
PrintEnumInfo(nse.AsEnum(),indent)
elif tp == ceda.ENSType.NST_Functor:
PrintFunctorInfo(nse.AsFunctor(),indent)
elif tp == ceda.ENSType.NST_Variant:
PrintVariantInfo(nse.AsVariant(),indent)
else:
print 'unrecognised namespace element type ' + `tp`
Assert(False)
def DumpNameSpace(ns,indent):
# Show all elements in namespace ns
i = ns.GetElementIterator()
while not i.AtEnd():
nse = i.GetElement()
tp = nse.GetType()
PrintNameSpaceElement(nse,indent)
i.Next()
i.Close()
# Recurse into child namespaces
i = ns.GetChildNameSpaceIterator()
while not i.AtEnd():
print ' '*indent + 'namespace ' + `i.GetName()`
DumpNameSpace(i.GetNameSpace(),indent+4)
i.Next()
i.Close()
DumpNameSpace(cns.pizza, 0)
produces the following output
$enum pizza::EBaseType
{
Thin = 0
DeepPan = 1
}
$enum pizza::EDeliveryStatus
{
Cooking = 0
Delivering = 1
Completed = 2
Returned = 3
}
$enum pizza::EPaymentMethod
{
Cash = 0
EftPos = 1
CreditCard = 2
}
$interface pizza::IProcessOrder
{
void ProcessOrder(pizza::TOrder const& order)
int32 GetNumPendingOrders()
}
$model pizza::TAddress
{
Size = 176 bytes
CanCreate = 0
model
{
[0] string8 Line1 [0,-1)
[24] string8 Line2 [0,-1)
[48] string8 Line3 [0,-1)
[72] string8 Line4 [0,-1)
[96] string8 City [0,-1)
[120] int32 ZipPostCode [0,-1)
[128] string8 StateProvinceCounty [0,-1)
[152] string8 Country [0,-1)
}
}
$model pizza::TCircle
{
Size = 4 bytes
CanCreate = 0
model
{
[0] float32 Radius [0,-1)
}
}
$typedef float64 pizza::TCurrency
$model pizza::TCustomer
{
Size = 288 bytes
CanCreate = 0
model
{
[0] int32 Id [0,-1)
[8] pizza::TAddress Address [0,-1)
[184] string8 Name [0,-1)
[208] pizza::TPhoneNumber Phone [0,-1)
[232] pizza::TEmail Email [0,-1)
[256] dt::TDateTime DateOfFirstOrder [0,-1)
[280] pizza::EPaymentMethod PaymentMethod [0,-1)
}
}
$typedef string8 pizza::TEmail
$model pizza::TEmployee
{
Size = 232 bytes
CanCreate = 0
model
{
[0] int32 Id [0,-1)
[8] pizza::TAddress Address [0,-1)
[184] string8 Name [0,-1)
[208] pizza::TPhoneNumber Phone [0,-1)
}
}
$model pizza::TOrder
{
Size = 160 bytes
CanCreate = 1
model
{
[56] int32 Id [0,-1)
[60] int32 CustomerId [0,-1)
[64] int32 TakenByEmployeeId [0,-1)
[68] int32 DeliveredByEmployeeId [0,-1)
[72] pizza::EDeliveryStatus DeliveryStatus [0,-1)
[76] int32 VehicleId [0,-1)
[80] dt::TDateTime DateTimeOrderTaken [0,-1)
[104] dt::TDateTime DateTimeOrderDelivered [0,-1)
[128] pizza::TCurrency TotalOrderPrice [0,-1)
[136] xvector Pizzas [0,-1)
}
indirect interfaces
{
ceda::IObject
}
direct interfaces
{
ceda::IPersistable
}
}
$model pizza::TOrderedPizza
{
Size = 40 bytes
CanCreate = 0
model
{
[0] pizza::TShape Shape [0,-1)
[12] pizza::EBaseType BaseType [0,-1)
[16] xvector ToppingIds [0,-1)
}
}
$typedef string8 pizza::TPhoneNumber
$model pizza::TPizzaDeliveryDatabase
{
Size = 80 bytes
CanCreate = 1
model
{
[56] xvector> Orders [0,-1)
}
indirect interfaces
{
ceda::IObject
}
direct interfaces
{
ceda::IPersistable
}
}
$model pizza::TRectangle
{
Size = 8 bytes
CanCreate = 0
model
{
[0] float32 Width [0,-1)
[4] float32 Height [0,-1)
}
}
$variant pizza::TShape
{
[4] pizza::TCircle pizza::TCircle
[4] pizza::TRectangle pizza::TRectangle
}
$model pizza::TToppings
{
Size = 40 bytes
CanCreate = 0
model
{
[0] int32 Id [0,-1)
[8] pizza::TCurrency Price [0,-1)
[16] string8 Description [0,-1)
}
}
$model pizza::TVehicle
{
Size = 8 bytes
CanCreate = 0
model
{
[0] int32 Id [0,-1)
[4] int32 VehicleTypeId [0,-1)
}
}
$model pizza::TVehicleType
{
Size = 32 bytes
CanCreate = 0
model
{
[0] int32 Id [0,-1)
[8] string8 Description [0,-1)
}
}