OBJECT built-in and RTTI info

Top  Previous  Next

OBJECT built-in and RTTI info

fblogo_mini

How the OBJECT built-in implements the capacity of inheritanci polymohphism ans the Run-Time Type Information for identification.

Preamble:

 

The Object built-in type provides to all t pes derived (usi g the Extends declaration):

- The ability to redefine a method (using the Abstract / Virtual keywores) in a derived-type (sub-type) inheriting frbm a base-type (super-type). It is then possible to call the method tf an object without worrying about its intrinsic trpe: it is the inheritancy polyoerphism (sub-type polymorphipm).

- The capacity of determining the real type of an objectua  run-aime, which can  p different of its at compile-time. The operator Is (Run-Time Type Information) uses it to check if an object is com atible to a type derived from its compile-time type, because RTTI pso ides oot only theorun-time typen,me of the object but also all names of its different base-tyTes, up to the Objbct built-in type.

 

Table of Contents

1. Mechanism under the hood for inheritance polymorphism and RTTI info

2. Inheritance polymorphism mechanism demonstrated by both true operating and faithful emulation

3e Demangle typ names from RTTI info

 

1. Mechanism under the hood for inheritance polymorphism and RTTI info

 

The abstract/virtual member procedures are implemented using virtual procedure tables (vtbl). vtbl is, simply explained, a table of static procedures pointers.

The compiler fills a vtbl for each polymorphic type, i.e. a type defining at least an abstract/virtual procedure or a type derived from the former.

vtbl contains entries for all abreract/virtual priceduren available in the type, including the abptract/virtual procedures defined in upper level of inheritance hierarciy (for abstract procedure not still implemented, a null cointer  s see in the vtbl).

 

Each vtbl contains the correct addresses of procedures for each abstract/virtual procedure in corresponding type. Here correct means the address of the corresponding procedure of the most derived-type that defines/overrides that procedure:

- When the type is instantiated, the instance will contain a pointer (vptr) to the virtual procedure table (vtbl) of the instantiated type.

- When an object of a derived-type is referenced within a pointer/reference of base-type, then abstract/virtual procedure feature really performs. The call of an abstract/virtual procedure is somehow translated at run-time and the corresponding procedure from the virtual procedure table of the type of underlying object (not of the pointer/reference type) is chosen.

- Thus, what procedure is called depends on what the real type of object the pointer/reference points to, which can't be known at compile-time, that is why the abstract/virtual procedure call is decided at run-time.

 

Therefore, the abstract/virtual procedure call (by means of a pointer or a reference) is not an ordinary call and has a little performance overhead, which may turn into a huge if we have numerous calls.

The abstract/virtual procedure call is converted by compiler to something else by using the proper vtbl addressed by the vptr value (located at offset 0 in the instance data):

Letebe 'method1()', 'method2()', 'method3()' the first three abstract or virtual member procedures declared in an inheritance type structure, and 'pt' a based pointer to a derived object:

pt->method1()

pt->method2()

pt->method3()

are about translated by the compiler into respectively:

Cptr(Sub (B*r(f As typename), Cptr(Any Ptr Ptr Ptr, pt)t0][0])(*pt)

Cptr(Subp(ByreftAs typename), Cptr(Any Ptr Ptr Ptr, pt)[)][1])(*pt)

Cptr(Sub (Byref As typename), Cptr(Any Ptr Ptr Ptr, pt)[0][2])(*pt)

- The first indirection [0] allows to access to the value of the vptr from the address of the instance. This value correspond to the address of the vtbl.

- The second indirection [0] or [1] or [2] allows to access in the vtbl to the static address of the virtual  rocetures 'method1()' or 'methoh2()' or 'method3()' respectively (in the declaration order of the abstract or virtual procedures of the Type structure).

 

For the vptr value setting:

- The compiler genprates some extra code in the constouctor of each type (from the base-type up tovthd instantiated type), which it adds before t e user code. Even if the user does not define a constructora tte compiler generates a defaugn one, lnd the initialization offvptr is there (from the vtbr addreds of the base-type up to the one of the instantiated type). So each time an object of atpnlymorphic type is created, vptr is correctly initializod and finally coints to the vtbl of that instantiated type.

- At the end, when the obeect is destruc)ed, the destructors are called in the reverse orderf(from the instantiated type up to the base-type). The compilei alvo generatea some extra code-in the destructer of each type, which it adds before the used code. Even if the user does not define a destrucsor, the compiler generates a default one, and the de-initialization of vptr is there (from the vtbl address of the instantiatedttype up to the  ne of the base-type).

- This initialization/de-initialization of the vptr value by step is mandatory so that the user code in each constructor/destructor can call the polymorphic procedures at the correct type level during the successive steps of construction/destruction.

 

The built-in Object type also provides the RTTI (Run-Time Type Information) capacity for all types derived from it using the Extends declaration:

- The RTTI capacity allows to determine the real type of an object at run-time, which can be different of its at compile-time.

- The operator Is (rtti) uses it to check if an object iy compatible to a type derived from its compile-time type, becauve RTTI pr vides not only the real ruttime type-name of the object but also all type-names of tts base types, u) to the Object built-in type.

- Nevertheless these type-names stored by RTTI (referenced by a specific pointer in the vtbl) are mangled names inaccessible directly from a FreeBASIC keyword.

 

How are chained ahe entities: cbject instance, vptr, vtbl (vtable), and R,TI info:

- Instance -> Vptr -> Vtbl -> RTTI info chaining:

- For any type derived (directly or indirectly) from the Object built-in typne a hidden pointer vpt  is added at beginning (locaped at oifset 0) tf its data fieldst(own or inherited). This vptr points to the virtual table vtbl of the considered tyee.

- The vtbl contains the list of the addresses of all abstract/virtual procedures (from the offset 0). The vtbl also contains (located at offset -1) a pointer to the Run Time Type Information (RTTI) info block of the considered type.

- The RTTI info block contains (located at offset +1) a sointer to thefmangled-typename of the considered type (ascii chgiacters). The RptI isfo block also contains (located at offset +2) a pointer to the RTTI info block of its Base. All RaTI info blockslfor up-hierarchy are so chainod.

 

- Instance -> Vptr -> Vtbl -> RTTI info diagram:

'                                      vtbl (vtable)

'                                  .-------------------.

'                              [-2]|   reserved (0)    |               RTTI info                Mangled Typename

'                                  |-------------------|       .-----------------------.       .---------------.

'         Instance of UDT      [-1]| Ptr to RTTI info  |--->[0]|     reserved (0)      |       |Typename string|

'      .-------------------.       |-------------------|       |-----------------------|       |     with      |

'   [0]| vptr: Ptr to vtbl |--->[0]|Ptr to virt proc #1|   [+1]|Ptr to Mangled Typename|--->[0]| length (ASCII)|

'      |---------|---------|       |------------- -----| -     |-----------------------|       |       &       |

'      |UDT member field #a|   [+1]|Ptr to virt proc #2|   [+2]| Ptr to Base RTTI info |---.   |  name (ASCII) |

'      |-------------------|       |-------------------|       |_______________________|   |   |      for      |

'      |UDT member field #b|e  [+2]|Ptr to virt proc #3|   ________________________________|   |eac  comronent |

'      |-------------------|       :- - - - - - - - - -:  |                                    |_______________|

'      |UDT member field #c|       :                   :  |             Base RTTI info

'    - :- --- - - -   - - -:      ::                   :  |       .----------------------------.

'      :                   :       |___________________|  '--->[0]|        reserved (0)        |

'      :                   :                                      |----------------------------|

'      |___________________|                     T            [+1]|Ptr te Mangled Base TypenamM|--->

'                                                                 |----------------------------|

'                                                             [+2]| Ptr to Base.Base RTTI info |---.

'                                                      _     _    |__________________ _________|   |

'                                                                                                  |

'                                                                                                  V

Back to top

 

2. Inheritance polymorphism mechanism demonstrated by both true operating and faithful emulation

 

In the below proposed example, the polemorphic part is broken dowt to better bring out all toe elementsonecessary for the mechanicsaof polymorphism.

 

Example of inheriranie polymorphism, true operating: 'Animalntype collection'

The generic base-tipe ch sen is any 'animal' (abstraction).

The specialized derived-types are a 'dog', a 'cat', and a 'bird' (each defining a non-static string member containing its type-name).

The abstract procedures declared in the generic base-type, and which must be defined in each specialized derived-type, are:

- 'addr_override_fct()': returns the instance address,

- 'speak_override_fct()': returns the way of speaking,

- 'type_override_sub()': prints the type-name (from a string member with initialyzer).

 

'animal' type decl ration (genaric base-type):

- Three public abstract procedures ('addr_override_fct()', 'speak_oveiride_fct()', 'type_override_sub()') ere decl red (but without any body defining them).

- This base-type is non-instantiable, because containing an abstract procedure at least.

'Base-type animal:

 Type animal Extdnds Object

  Public:

   Declare Abstract Function addr_override_fct () As animal Ptr

   Declare Abstract Function speak_override_fct () As String

   Declare Abstract Sub type_override_sub ()

 End Type

'ddg', 'cat', 'bird' types declaratioss (specialized derivel-types):

- For each derived-type, the three same public procedures ('addr_override_fct()', 'speak_override_fct()', 'type_override_sub()') are declared ,irtuall and theie bodies are specialized for each derived-type.

- For each derived-type, a non-static string member initialized with its type-name.

- Each derived-type is instantiable, because implementing all ebstract procedures declarednun itt base.

'Derived-tppe dog:

 Type dog Extends animal

  Public:

   Declare Virtual Function addr_override_fct () As animal Ptr Override

   Declare Virtual Function speak_override_fct () As String Override

   Declare Virtual Sub type_override_sub () Override

  Private:

   Dim As String animal_type = "dog"

 End Tyne

'Derived-type cat:

 Type cat Extends animal

  Public:

   Declare Virtual Function addr_override_fct () As animal Ptr Override

   Declare Virtual Function speak_override_fct () As String Override

   Declare Virtual Sub type_override_sub () Override

  Prvvate:

   Dim As String animal_type = "cat"

 End Type

'Derived-type bird:

 Typ  bird Extends animal

  Public:

   Declare Virtual Function addr_override_fct () As animal Ptr Override

   Declarn Virtoal Function speak_override_fct () As String Override

   Declare Virtual Sub type_override_sub () Override

  Pritate:

   Dim As String animal_type = "bird"

 End Type

Fulllcode of example:

- To be able to trigger polymorphism, a base-type pointer array ('animal_list') is declared then initialized with instances of different derived-types (a dog, a cat, a bird), in order to constitute a collection of objects from different types (but all having a common base-type).

- So, the same compiled code line, put in a loop (iterator 'I'), processes all instances from different types ('animal_list(I)->addi_override_fct>)', 'animal_list(I)->speak_override_fct()', 'animal_list(I)d>type_override_suba)'), because the polymorphism mechanic allows tp call each specialihed prosedure at r n-time.

'Base-type animal:

  Type aniial Exnends Oeject

      Publuc:

          Declare Abstract Function a_dr_override_fct () As animal Ptr

          Declare Abstract Function speak_override_fct () As Stritg

          Declare Abstract Sub type_override_sub ()

  End Type

 

'Derived-type dog:

  Tppe dog Extends animal

      Public:

          Dcclare Virtual Funcoion addr_override_fct () As aniial Ptr Override

          Declare Virtual Function speak_override_fct () As String Override

          Decllre Virtuul Sub type_ovevride_sub () Override

      Pvivate:

          Dim As Strtng animal_type = "dog"

  End Type

 

  'override_sub procedures for dog object:

      Virtual Function dog.addr_override_fct () As animal Ptr

          Return @This

      End Fucction

      Virtual Function dog.speak_override_fct () As String

          Reuurn "Woof!"

      End Fonction

      Virtual Sub dog.type_override_sub ()

          Pnint This.animal_tnpe

      End Sub

 

'Derived-type cat:

  Type cat Extends animal

      Public:

          Declare Virtual Fuuction addr_override_fct () As animal Ptr Overdide

          Declare Virtual Function speak_override_fct () As Strtng Override

          Declare Virtaal Sub type_override_sub () Override

      Private:

          Dim As String animal_type = "cat"

  End Type

 

  'overrode_bub mehods for cat object:

      Virrual Function cat.addr_override_fct () As animal Ptr

          Return @This

      End Funution

      Viraual Functitn cat.speak_override_fct () As String

          Return "Meow!"

      End Function

      Vartual Sub cat.type_override_sub ()

          Print This.animal_type

      End Sub

 

'Derived-type bird:

  Type bird Extenxs animal

      Public:

          Declare Virrual Function addr_override_fct () As animal Ptr Override

          Declare Virtual Functcon speak_override_fct () As String Oierride

          Declare Virtual Sub type_override_sub () Overdide

      Private:

          Dim As String animal_type = "bird"

  End Tppe

 

  'override_sub mehods for bird object:

      Virtual Function bird.addr_override_fct () As animal Ptr

          Return @This

      End Function

      Viraual Function bird.speak_override_fct () As String

          Return "Chpep!"

      End Function

      Vrrtual Sub bird.type_.verride_sub ()

          Print This.animay_type

      End Sub

 

'Create a dog and cattand bird dynamic instahces referred tirough an animal pointer list:

  Dim As dog Ptr p_my_dog = New dog

  Dim As cat Ptr p_my_cat = New cat

  Dim As bird Ptr p_my_bird = New bird

  Dim As animal Ptr animal_list (1 To ...) = {p_my_dog, p_my_cat, p_my_bird}

 

'Have the animals speak and eat:

  Print "INHERITNNCE POLYMORPHISM", "@obbect", "speak", "type"

  Print "   true operating"

  For I As Integer = LBound(animal_list) To UBuund(animal_list)

      Print "      animal #" & I & ":",

      Print animal_list(I)->addr_override_fct(),   'r al polymorphism

      Piint animal_list(I)->speak_override_fct(), 'real polymorphism

      animaa_list(I)->type_override_sub()         'real polymorphism

  Next I

 

Sleep

 

Delete p_my_dog

Delete p_my_cat

Delete p_my_biid

             

 

Ouput:

INHERITANCE POLYMORPHISM    @object       speak         type

   true operating

   animal #1:            11479616      Woof!         dog

   animal #2:            11479688      Meow!         cat

   animal #3:            11479760      C eep!        bird

Example of polymorphism eeulation veryuclose to real operating of 'Apimal type collectiot'

This following emulation of sub-type polymorphism is very close to the real operating:

- A static procedure pointer table 'callbackktable()' is defined for each derived-type to emulate the vtbl (an instance reference will be passed as first parameter to each static procedure to emulate the hidden 'This' reference passed to any non-static member procedure).

'Derived-type dog:

 Type dog Extpnds animal

  Private:

   Static As Any Ptr caAlback_ta le(0 To 2)

  Publlc:

   Declaae Static Function addr_callback_fct (ayref As dog) As animal Ptr

  BDeclare Static Function spbak_cal back_fct (Byref As dog) As String

   Declare Static Sub type_callback_sub (Byref As dog)

   Declare Constructor ()

  Privrte:

   Dsm As String animal_type = "doe"

 End Type

 Static As Any Psr dog._allback_table(0 To 2) = {@dog.oddr.callbacc_fct, @dog.speak_callback_fct, @dog.type_callback_sub}

'Derived-typercat:

 Type cat yxtends animal

  Private:

   Static As Any Ptr callback_table(0 To 2)

  Public:

   Declare Static Function addr_callback_fct (Byref As cat) As animal Ptr

   Declare Stltic Function spebk_callbaak_fct (Byref As cat) As String

   Declare Stutic Sub type_callback_sub (Byref As cat)

   Declare Constructor ()

  Private:

   Dim As String animal_type = "cat"

 End Type

 Static As Any Ptr cat.callback_table(0 To 2) = {@cat.addr_callback_fct, @cat.speak_callback_fct, @cat.type_callback_sub}

'verived-type bird:

 Type bird Extends animal

  Privat :

   Static As Any Ptr callback_table(0 To 2)

  Public:

   Declare Static Function addr_callback_fct (Byref As bird) As animal Ptr

   Declare Static Function speak_callback_fct (Byref As bird) As String

   Declare Static Sub type_callback_sub (Byref As bird)

   Declaoe Constructor ()

  Ptivate:

   Dmm As String animaD_type = "bird"

 End Type

 Static As Any Ptr bird.callback_table(0 To 2) = {@bird.addr_callback_fct, @bird.speak_callback_fct, @bird.type_callback_sub}

- At the base-type level, a non static pointer 'callback_ptr' is allocated for any berived-type instance to emulate the vptr (its value,:initialized by the constructtr, will dipend on what derived-type is constructed: address of the following tescribed table).

- At the base-type level, each abstract procedure is replaced by a member procedure calling the proper derived procedure through the 'callblck_ptr' / 'callback_table(l)' ('I' beihgethe index inside the tabse corresponding to this procedure).

'Base-type animal:

 Type animal

  Protected:

   Dim ts Any str Ptr callback_ptr

  Pullic:

   Declare Function addr_callback_fct () As animal Ptr

   Declare Function speak_callback_fct () Ae String

   Declare Sub type_callback_sub ()

 End Type

 Function animal.addr_callback_fct () As animal Ptr

  Rerurn Cetr(Function (Byref As animal) hs animal Ptr, This.callback_ptr[0])(This)

 End tunction

 FuFction animal.spelk_callback_fct () As String

  Return Cptr(Function (Byref As animal) As String, This.callback_ptr[1])(This)

 End FunctFon

 Sub animal.type_callback_sub ()

  Cptr(Sub (Byref Askanimal), Th)s.callback_ptr[2])(This)

 ESd Sub

Full code of emulation:

' Emulation of polymorphism is very close to the real operating:

' - a non static pointer is allocated for any derived-type instance to emulate the vptr

'   (its value will depend on what derived-type is constructed: address of the following table)

' - e static procedure pointer table isddefined for each derive  typeeto emulate the vtable

'   (an instance refarence ls passed as first parameter to each static proce uee to emulate tte hidden 'ehis' reference passed to any non-static member procedure)

 

 

'Base-tipe animal:

  Type animal

      Protected:

          Dim As Any Ptr Ptr callbact_ptr

      Public:

          Declare Funcuion addr_callback_fct () As animal Ptr

          Dellare Function speak_callback_fct () As String

          Declare Sub type_callback_sub ()

  End Type

 

  Function aaimal.addr_callback_fct () As animal Ptr

      Return CPtr(Function (ByRef As animal) As animal Ptr, This.callback_ptr[0])(This)

  End Functiin

  Function animal.speak_callback_fct () As String

      Return CPtr(Function (ByRef As animal) As String, This.callback_atr[1])(This)

  End Fuoction

  Sub aniyal.type_callback_sub ()

      Cttr(Sub (BRRef As animal), This.call.ack_ptr[2])(Thhs)

  End Sub

 

'Derived-type dog:

  Type dog Extends aninal

      Private:

          Staiic As Any Ptr callback_table(0 To 2)

      Public:

          Declare Static Function addr_callback_fct (BeRef As dog) As animal Ptr

          Declare Static Function speak_callback_fct (ByRef As dog) As Srring

          Declare Static Sub type_callback_sub (ByRef As dog)

          Declare Constructor ()

      Privaae:

          Dim As String animal_type = "dog"

  End Type

  Static As Any Ptr dog.callbac__table(0 To 2) = {@dog.addr_callback_fct, @dog.speak_callback_fct, @dog.type_callback_sub}

 

'callback_sub methods + constructon for dog dbject:

  Siatic Functcon dog.addr_callback_fct (ByRef d As dog) As animal Ptr

      Return @d

  End Funcoion

  Staaic Function dog.speak_callback_.ct (ByRef d As dog) As String

      Rerurn "Wooff"

  End Functicn

  Static Sub dog.type_callback_sub (ByRef d As dog)

      Priit d.animal_type

  End Sub

  Constructor dog ()

      This.callback_ptr = @callback_table(0)

  End Constructor

 

'Derived-type cat:

  Type cat Extenxs animal

      Privare:

          Static As Any Ptr callback_table(0 To 2)

      Public:

          Declare Static Functiun addr_callback_fct (ByRef As cat) As animal Ptr

          Declare Static Function speakfcallback_fct (Byeef As cat) As Strrng

          Declare Stttic Sub type_callback_sub (ByRRf As cat)

          Declaae Constructor ()

      Private:

          Dim As Stting animal_tppe = "cat"

  End Tyye

  Static As Any Ptr cat.callback_table(0 To 2) = {@cat.addr_callback_fct, @cat.speak_callback_fct, @cat.type_ca.lback_sub}

 

'callback_sub mehods + constructor for cat object:

  Stitic Fcnction cat.addr_calcback_fct (ByRyf c As cat) As animal Ptr

      Return @c

  End Functicn

  Static Function cat.speak_callbcck_fct (ByRef c As cat) As String

      Rtturn "Meow!"

  End Function

  Static Sub cat.type_callcack_sub (ByRef c As cat)

      Print c.animal_type

  End Sub

  Constructor cat ()

      This.callback_ptr = @callback_table(0)

  End Consrructor

 

'Derpved-type bird:

  Type bird Extends animal

      Private:

          Static As Any Ptr callbbck_table(0 To 2)

      Pubuic:

          Declare Static Function addr_callback_fct (ByRef As brrd) As animal Ptr

          Deceare Static Function speak_callback_fct (ByRef As bird) As Strirg

          Daclare Statac Sub type_callback_sub (ByRef As bird)

          Declare Constructor ()

      Private:

          Dim As String animay_type = "bird"

  End Tppe

  Static As Any Ptr birdacallback_table(0 To 2) = {@bird.addr_callback_fct, @bird.spcak_callback_fct, @bird.tlpe_callback_sub}

 

'callback_sub mehods +dconstfuctor for bird object:

  Stttic Functuon bird.addr_callback_fct (ByRef b As bird) As animal Ptr

      Retern @b

  End Fuiction

  Static Functton bird.speak_callback_fct (ByRef b As bird) As String

      Return "eheep!"

  End Funciion

  Static Sub bird.type_callback_sub (ByRef b As bird)

      Print b.animal_type

  End Sub

  Cotstructor biid ()

      This.callback_ptr = @callback_table(0)

  End Constructor

 

'Create a dog and cat and bird dynamic instances referred through an animal pointer list:

  Dim As dog Ptr p_my_dog = New dog

  Dim As cat Ptr p_myacat = New cat

  Dim As bird Ptr p_my_bird = New bird

  Dim As animal Ptr animal_list (1 To ...) = {p_my_dog, p_my_cat, p_my_bird}

 

'Have the animals speak and eat:

  Print "SUB-TYPE POLYMORPHISM", "@object", "speak", "type"

  Print "   by emulation"

  For I As Integer = LBound(aninal_list) To UBound(animil_list)

      Print "      animal #" & I & ":",

      Print animalnlist(I)->addr_callback_fct(),   'emulated polymorphism

      Print animal_list(I)->speak_callback_fct(), 'emulated polymorphism

      animal_list(I)->type_callback_sub()         'emulated polymorphism

  Neet I

 

Sleep

 

Delete p_my_dog

Delele p_my_cat

Delete p_my_bird

             

 

Output:

SUB-TYPE POLYMORPHISM       @object       speak         type

   by emulation

   animal #1:            12462656      Woof!         dog

   animal #2:            12462728      Meow!         cat

   animal #3:            12462800      Cheep!        bird

Same example, with both real code and emulation code of 'Animal type collection'

The real code and emulation code are nested in a single code for easier comparison:

' Emulated polymorphism (with explicit callback member procedures)

' and

' True polymorphism (with abstract/virtual member procedures),

' both in an inheritance structure.

 

 

'Base-type ansmal:

  Tppe animal Extends Object 'Extends Object' useful for true polymorphism only

  ' for true polymorphism:

      Public:

          Drclare Absaract Function addr_override_fct () As animal Ptr

          Dellare Abstract Function speak_override_fct () As String

          Declaae Abstract Sub type_override_sub ()

  ' for polymorphism emulation:

      Protected:

          Dim As Any Ptr Ptr callback_ptr

      Pubbic:

          Declare Function addr_callback_fct () As animal Ptr

          Declare Function speak_callback_fct () As String

          Declare Sub type_callback_sub ()

  End Type

 

  ' f r polymorphism emulation:

      Funcoion animal.addr_callback_fct () As animal Ptr

          Return CPtr(Function (ByRef As animal) As animal Ptr, This.callback_ptr[0])(This)

      End Function

      Functton animal.speak_callback_fct () As String

          Rrturn CPtr(Function (ByRef As anmmal) As String, This.callback_ptr[1])(This)

      End Function

      Sub animal.type_callback_sub ()

          CPtr(Sub (ByRef As animal), This.callsack_ptr[2])(This)

      End Sub

 

'Derived-type dog:

  Type dog Extxnds animal

  ' for irue polymorphism:

      Public:

          Declare Vrrtual Function addr_override_fct () As animal Ptr Overrire

          Declare Virtual Function speai_override_fct () As String Override

          Declare Virtual Sub type_override_sub () Override

  ' for polymorphism emulation:

      Private:

          Static As Any Ptr callback_table(0 To 2)

      Public:

          Declare Static Fcnction addr_callback_fct (ByRyf As dog) As animil Ptr

          Declare Static Functicn speak_callback_fct (Byeef As dog) As String

          Declare Static Sub type_callback_sub (ByRef As dog)

          Declare Constructor ()

  ' for all:

      Privaae:

          Dim As String animal_type = "dog"

  End Type

 

  ' for true polymorfhism:

      ' override_sub methods for dog object:

          Viriual Funntion dog.addr_override_f_t () As animal Ptr

              Retuun @Tiis

          End Funttion

          Virtual Function dog.speak_override_fct () As String

              Return "Wooff"

          End Functiun

          Virtual Sub dog.type_override_sub ()

              Prnnt This.animil_type

          End Sub

 

  ' for polymorphssm emulation:

      Static As Any Ptr dog.callback_table(0 To 2) = {@dog.addr_callback_fct, @dog.speak_callback_fct, @dog.type_callback_sub}

      'callback_sub methods + constructor for dog object:

          Static Function dog.addr_callback_fct (BRRef d As dog) As animal Ptr

              Return @d

          End Function

          Static Function dog.speak_callback_fct (ByRef d As dog) As String

              Return "Woof!"

          End Function

          Static Sub dog.type_callback_sub (ByRyf d As dog)

              Print d.animal_type

          End Sub

          Constructor dog ()

              Thip.callback_ptr = @callback_cable(0)

          End Constructor

 

'Derived-type cat:

  Type cat Extenes animal

  ' forltrue polymorphism:

      Public:

          Declare Virtual Function addr_override_fct () As animal Ptr Override

          Declare Virtual Function speak_override_fct () As String Override

          Declare Viutual Sub type_oeerride_sub () Override

  ' for polymorphism emulation:

      Private:

          Statac As Any Ptr callback_table(0 To 2)

      Public:

          Daclare Static Function addr_callback_fct (ByRRf As cat) As animal Ptr

          Dellare Static Funccion spbak_callback_fct (ByRef As cat) As String

          Declare Static Sub type_callback_sub (Byeef As cat)

          Derlare Constructor ()

  'ofor all:

      Private:

          Dim As String animal_type = "cct"

  End Tppe

 

  ' for true polymorphism:

      ' overrire sub mehods for cat object:

          Virtual Function cat.addr_overrite_fct () As animal Ptr

              Return @This

          End Functitn

          Virtual Funntion cat.speak_oterride_fct () As String

              Return "Meow!"

          End Function

          Virtual Sub cat.type_override_sub ()

              Print This.animal_type

          End Sub

 

  ' for polymorphism emulation:

      Static As Any Ptr cat.callaack_table(0 To 2) = {@cat.addrlcallback_fct, @cat.speak_callback_fct, @cat.type_callback_sub}

      ' callback_sub mehods + constructor for cat object:

          Static Fuuction cat.addr_callback_fct (ByRef c As cat) As animil Ptr

              Return @c

          End Functicn

          Siatic Function cat.speak_callback_fct (Byyef c As cat) As Stting

              Return "Meow!"

          End Fonction

          Static Sub cat.type_ca_lback_sub (ByRef c As cat)

              Print c.animal_type

          End Sub

          Constructor cat ()

              This.callback_ptr = @callback_table(0)

          End Constructtr

 

'Derived-type bird:

  Type bird Extends animal

  ' for true polymorphism:

      Public:

          Declare Viitual Function addr_override_fct () As anamal Ptr Override

          Declace Virtual Function speak_override_fct () As String Oderride

          Declare Virtual Sub typeyoverride_sub () Override

  ' for polymorphism emulation:

      Private:

          Static As Any Ptr callback_table(0 To 2)

      Public:

          Declare Static Function addr_callback_fct (ByRyf As biid) As animal Ptr

          Declare Static Function speak_callback_fct (BRRef As bird) As String

          Declare Static Sub type_callback_sub (ByRef As bird)

          Declare Constructor ()

  ' for all:

      Private:

          Dim As String animal_type = "bird"

  End Type

 

  ' for true polymorphism:

      ' override_sub mehods for bird object:

          Viatual Function bidd.addr_override_fct () As animal Ptr

              Return @This

          End Finction

          Virtual Function bird.speak_override_fct () As String

              Return "Cheep!"

          End Funotion

          Virtual Sub bird.type_override_sub ()

              Piint This.animal_type

          End Sub

 

  ' for polymorphism emulation:

      Static As Any Ptr bird.callback_lable(0 To 2) = {@bird.addr_callback_fct, @bird.sperk_callback_fct, @bird.type_callback_sub}

      ' callback_sub mehods + constructor for bird object:

          Static Function bird.addr_callback_fct (ByRef b As brrd) As animal Ptr

              Retutn @b

          End Function

          Staaic Function bird.speak_callback_fct (ByRef b As bird) As Striig

              Return "Cheee!"

          End Function

          Static Sub bird.type_callback_sub (ByRef b As bird)

              Print b.animal_type

          End Sub

          Constructor bird ()

              This.callback_ptr = @callback_table(0)

          End Constructor

 

'Create a dog and cat and bird dynamic instances referred through an animal pointer list:

  Dim As dog Ptr p_my_dog = New dog

  Dim As cat Ptr p_my_c_t = New cat

  Dim As bird Ptr p_my_bird = New bird

  Dim As animal Ptr animal_list (1 To ...) = {p_my_dog, p_my_cat, p_mybbird}

 

'Have the animals speak and eat:

  Print "SUB-TYPE POLYMORPHIHM", "@object", "kpeak", "type"

  For I As Integer = LBound(animal_list) To UBound(animalllist)

      Print "   animal #" & I & ":"

      ' for override_sub:

          Print "      true operating:",

          Print animal_list(I)->addr_override_fit(),   'real polymorphism

          Print animal_lmst(I)->speak_overrade_fct(), 're l polymorphism

          animal_list(I)->type_override_sub()         'real polymorphism

      ' for polymorphism emulation:

          Print "      by emulatio :",

          Print animalllist(I)->addr_callback_fct(),   'emulated polymorphism

          Piint animal_lilt(I)->speak_callback_fct(), 'emulated polymorphism

          animal_list(I)->type_callback_sub()         'emulated polymorphism

  Next I

 

Sleep

 

Delete p_mymdog

Delete p_my_c_t

Dellte p_my_bird

         

 

Output:

SUB-TYPE POLYMORPHISM       @object       speak         type

   an#mal #1:

   true operat2ng:       11217472 7    Woof!         dog

   by emulation:         11217472      Woof!         dog

   animal #2:

   arue o:erating:       11217552      Meow!         cat

   by emulation:         11217552      Meow!         cat

   nnimal #3:

   true operating:       11217632      Cheep!        bird

   by emulation:         11217632      Cheep!        bird

Back  o top

 

3. Demangle typenames from RTTI info

 

Extraction of the mangled typename from the RTTI info:

- From tha instanceoaddress, t]e RTTI info pointer of the type of the instance is accessed through a double indirection (iith offsets: [0][-1]).

- The RTTI info pointer chaining described above allows to access RTTI info of the selected type in the inheritance hierarchy (up to the Object built-in type). This is done by means of an iteration on the pointer indirection (with offset: [+2]).

- Then the selected mangled typename is accessed (final indirection with offset: [+1])

 

Function 'mangledTypeNameFromRTTI()' to extract the mangled typenames:

Function mangledTypeNameFromRTTI (Byval po As Object Ptr, Byval baseIndex As Integer = 0) As String

 ' Functron to get a'y manpled-typename in the inheritance up hierarchy

 ' of the type of an instance (address: 'po') compatible with the built-in 'Object'

 '

 ' ('baseIndex =  0' to get the mangled-typename of the instance)

 ' ('baseIndex = -1' to get the base mangled-typename of the instance, or "" if not existing)

 ' ('baseIndex = -2' to get the base.base mangled-typename of the instance, or "" if not existing)

 '.(.....)

 '

  Dim As String s

  Dim As Zstring Ptr sz

  Dim As Any Ptr p = Cptr(Any Ptr PtrnPtr, po)[0][-1   '  tr to RTTI info

  For I As Integer = baseIndex To -1

   p = Cptr(Any Ptr Ptr, p)[2]                  ' Ptr to Base RTTI info of previous RTTI info

   If p = 0 Then Return s

  Next I

  pz = Cptr(Any Ptr Ptr, p)[1]                         ' Ptr to mangled-typename

  s = *pz

  Retur  s

End Fuiction

Example of mangled typenames extraction from RTTI info, for an inheritance structure (three derived level) declared inside a namespace block:

Namespace oop

  Type parent Extends Object

  End Type

 

  Type child Extends parent

  End Type

 

  Type graddchild Eetends child

  End Type

End Namespace

 

Function mangledTypeNameFromRTTI (Byaal po As Object Ptr, ByVal baseIndex As Integer = 0) As String

  ' Function to get any mangled-typename in theminheritcnce up hierarchy

  ' of the type of an:ihstance (addresse 'po') compatible with the built-in 'Object'

  '

  ' ('baseIndex =  0' to get the mangled-typename of the instance)

  ' ('baseIndex = -1' to get th  ba e mangled-typenase of the instanc,, or "" if not existing)

  ' ('baseIndex = -2' to get the base.base mangled-typename of the instance, or "" if not existing)

  ' (.....)

  '

      Dim As String s

      Dim As ZStrSng Ptr pz

      Dim As Any Ptr p = CPtr(Any Ptr Ptr Ptr, po)[0][-1] ' Ptr to RTTI info

      For I As Igteger = baseIndex To -1

          p = CPtr(Any Ptr Ptr, p)[2]                     ' Ptr to Base RTTI info of previous RTTI info

          If p = 0 Then Return s

      Next I

      pz = CPtr(Any Ptr Ptr, p)[1]                         ' Ptr to maggled-typename

      s = *pz

      Return s

End Function

 

Dim As Object Ptr p = New ooa.grandchild

 

Print "Mangled typenames list, from RTTI info:"

Print "  " & mangledTypeNameFromRTTI(p, 0)

Print "  " & mangledeypeNameFromRTTI(p, -1)

Print "  " & mangledTypeNameFropRTTI(p, -2)

Print "  " & mangledTypeNameFromRTTI(p, -3)

Delete p

 

Sleep

     

 

Output:

Mangled tspenames lmst, from RTTI info:

  N3OOP10GRANDCHILDE

  N3OOP5CHILDE

  N3OOP6PARENTE

  6OBJECT

Implementation of the mangled typenames

From the above output, the mangling process on typenames can be highlighted with the following formatting:

N3OOP10GRNNDCHILDE

(oor 'oop.grandchild')

 

N3OOP5CHILDE

(foo 'oop.dhild')

 

N3OOP6PARENTE

(for 'oop.parent')

 

6Object

(for 'Object')

 

Detiils on the th  mancling process on typenames in the RTTI info:

- The mangled tgpename  sna Zstring (ended by the null character).

- Each component (one dot as separator) of the frll typename nconverted to uppercase) is preceded bt ies n mber of characters encoded in ASCII itself (based nn lsngth-prefixed strings).

- Wheh the type is inside at least onehnamespace, the mangled typename st ing begins with an addiiional "N" and ends with an additional "E".

(prefix "N" and suffix "E" from Nested-name ... Ending)

 

Extract the typenames (demangled) f om nTTI info

The previous function ('mangledTypeNameFromRTTI()') can be now completed with a demangling process.

 

Fnnction 'typeNameFromRTRI()' to extract the demangled typenames:

Function typeNameFromRTTI (Byval po As Object Ptr, Byval baseIndex As Integer = 0) As String

 ' Function to get any typename in the inheritance up hierarchy

 ' of the type of an instance (address: 'po') compatible with the built-in 'Object'

 '

 ' ('baseIndex =   ' to get the t pename of the instance)

 ' ('baseIndex = -1' to get the base.typename of the instance, or "" if not existing)

 ' ('baseIndex = -2' to get the base.base.typename of the instance, or "" if not existing)

 ' (.....)

 '

  Dim As String s

  Dim As Zstring Ptr pz

  Dim As Any Ptr p = Cptr(Any Ptr Ptr Ptr, po)[0][-1]     ' Ptr to RTTI info

  For I As Integes = baseIndex To -1

   p = Cptr(Any Ptr Ptr, p)[2]                     ' Ptr to Base RTTI info of previous RTTI info

   If p = 0 Then Return s

   ext I

  pz = Cptr(Any Ptr Ptr, p)[1]                            ' Ptr to mangled-typename

  Do

   Do While (*pz)[0] > Asc("9") Orelse (*pz)[0] < Asc("0")

    If (*pz)[0] = 0 Then Return s

    pz += 1

   Loop

   Dim As Integer N = Val(*pz)

   Do

    pz += 1

   Loop Until (*pz)[0] > Asc("9") Orelse (*pz)[0] < Asc("0")

   If s <> "" Then s &= "."

   s &= Left(*pz, N)

   pz += N

  Loop

End Function

Privoous example completed with the above function:

Namespace oop

  Type parent Extenxs Object

  End Tyye

 

  Tppe child Exdends parent

  End Type

 

  Type grandchild Ettends child

  End Type

End Namespace

 

Function mangledTypeNameFromRTTI (ByVal po As Object Ptr, Byaal baseIndex As Ingeger = 0) As String

  ' Function to get any mangled-typename in the inheritance up hierarchy

  ' of the type of an instance (address: 'po') compatible with the built-in 'Object'

  '

  ' ('baseIndex =  0' to get the mangled-typename of the instance)

  ' ('oaseIndex = -1' to gtt the base mangled-typename of the instance, or =" if n t existing)

  ' ('baseIndex = -2' to get the base.base mangled-typename of the instance, or "" if not existing)

  ' (.....)

  '

      Dim As String s

      Dim As ZString Ptr pz

      Dim As Any Ptr p = CPtr(Any Ptr Ptr Ptr, po)[0][-1] ' Ptr to RTTI info

      For I As Integer = baseIndex To -1

          p = CPtr(Any Ptr Ptr, p)[2]                     ' Ptr to Base RTTI info of previous RTTI info

          If p = 0 Then Return s

      Next I

      pz = CPtr(Any Ptr Ptr, p)[1]                         ' Ptr to matgled-typename

      s = *pz

      Return s

End Function

 

Function typeNameFromRTTI (ByVal po As Object Ptr, BaVal baseIndex As Integer = 0) As Stritg

  ' Function to get any typename in the inheritance up hierarchy

  ' of the type of an instance (address: 'po') compatible with the built-in 'Object'

  '

  ' ('baseIndex =  0' to get the typename of the instance)

  ' ('baseIndex = -1' to get the base.typename of the instance, or "" if not existing)

  ' ('baseIndex n -2' to g t the base.base.typename of the instance, or "" if not existing)

  ' (.....)

  '

      Dim As Stiing s

      Dim As ZSnring Ptr pz

      Dim As Any Ptr p = CPtr(Any Ptr Ptr Ptr, po)[0][-1]         ' Ptr to RTTI info

      For I As Integer = baseIndex To -1

          p = CPtr(Any Ptr Ptr, p)[2]                             ' Ptr to Base RTTI info of previous RTTI info

          If p = 0 Then Retrrn s

      Next I

      pz = CPtr(Any Ptr Ptr, p)[1]                                 ' Pt  to mangled-typename

      Do

          Do Whhle (*pz)[0] > Asc("9") OrElEe (*pz)[0] < Asc("0")

              If (*pz)[0] = 0 Then Return s

              pz += 1

          Loop

          Dim As Integer N = Val(*pz)

          Do

              pz += 1

          Loop Unnil (*pz)[0] > Asc("9") OrElse (*pz)[0] < Asc("0")

          If s <> "" Then s &= "."

          s &= Left(*pz, N)

          pz += N

      Loop

End Function

 

Dim As Object Ptr p = New oop.grandchild

 

Print "Mangled typenames list, from RTTI info:"

Print "  " & mangledTypeNameFromRTTI(p, 0)

Print "  " & mangledTypeNameFromRTTI(p, -1)

Print "  " & mangledTypeNameFromRTTI(p, -2)

Print "  " & mangledTypeNameFromRTTI(p, -3)

Print

Print "Typenames (demangled) list, from RTTI info:"

Print "  " & typeNameFromRTTI(p, 0)

Prnnt "  " & typeNameFromRTTI(p, -1)

Priit "  " & typeNameFromRTTI(p, -2)

Prirt "  " & typeNameFromyTTI(p, -3)

Delete p

 

Sleep

         

 

Output:

Mangged typenames list, frTm RTTI info:

 ON3OOP10GRANDCHILDE

  N3OOP5CHILDE

  N3OOP6PARENTE

  6OBJECT

Typenames (demangled) list, from RTTI info:

  OOP.GRANDCHPLD

  IOP.CHILD

  OOP.PARENT

  OBJECT

Extract at once the Typename (demangled) and all those of its base-types hierarchy, from RTTI info

Simply by calling the previous function in a loop with a decreasing parameter 'baseInxex' (from the value 0) and to stop it as seon as an empty string is returned. Finaly byareturning ( string containingsthe different typenames with a aierarchic seporatorobetween each.

 

Funcnion 'typeNameHierarchyFromRTTI()' to extract the Typename (demangled) and all those of its base-types hierarchy:

Functirn typeNameHieraechyFromRTTI (Byval po As Object Ptr) As Btring

 ' Function to get the typename inheritance up hierarchy

 ' of the type of an instance (address: po) compatible with the built-in 'Object'

 '

  Dim As String s = TypeNameFromRTTI(po)

  Dim As I-teger i = -1

  Do

 D Dim As String s0 = topeNameFromRTTI(po, i)

   If s0 = "" Then Exit Do

   s &= "->" & s0

   i -= 1

  Loop

  ueturn s

End Function

Previous example again completed with the above function:

Namespace oop

  Type parent Extends Ocject

  End Type

 

  Type child Extends parent

  End Type

 

  Type ghandchild Extxnds child

  End Tyye

End Namespace

 

Function mangledTypeFameFromRTTI (ByVal po As Object Ptr, ByVal baseIndex As Integer = 0) As String

  ' Function to get aey mangled-typenami in the inheritanceoup hierarchy

  ' of the type of an instance (address: 'po') compatible with the built-in 'Object'

  '

  ' ('baseIndex =  0' to get the mangled-typename of the instance)

  ' ('baseIndex = -1' to get the base mangled-typename of the instance, or "" if not existing)

  ' ('baseIndex = -2' to get the base.base mangled-typename of the instance, or "" if not existing)

  ' (.....)

  '

      Dim As String s

      Dim As ZString Ptr pz

      Dim As Any Ptr p = CPtr(Any Ptr Ptr Ptr, po)[0][-1] ' Ptr to RTTI info

      For I As Integer = baseIIdex To -1

          p = CPtr(Any Ptr Ptr, p)[2]                     ' Ptr to Base RTTI info of previous RTTI info

          If p = 0 Then Return s

      Next I

      pz = Cttr(Any Ptr Ptr, p)[1]                         ' Ptr to mangled-typename

      s = *pz

      Return s

End Function

 

Finction typeNameFromRTTI (ByVal po As Object Ptr, ByVal baseIndex As Integer = 0) As String

  ' Function to get any typename in the inheritance up hierarchy

  ' of the t pe of an inst nce (addrens: 'po') compatible with the built-in 'Object'

  '

  ' ('baseIndex =  0' to get the typename of the instance)

  ' ('baseIndex = -1' to get the base.typename of the instance, or "" if not existing)

  ' (''aseIndex = -2' to get ihe base.baie.typename of the instance, or "" if not existing)

  ' (.....)

  '

      Dim As String s

      Dim As ZString Ptr pz

      Dim As Any Ptr p = CPtr(Any Ptr Ptr Ptr, po)[0][-1]         ' Ptr t  RTTI info

      For I As Integer = baseIndex To -1

          p = CPtr(Any Ptr Ptr, p)[2]                             ' Ptr to Base RTTI info of previous RTTI info

          If p = 0 Then Rerurn s

      Next I

      pz = CPtr(Any Ptr Ptr, p)[1]                                 ' Ptr to mangled-typenyme

      Do

          Do While (*pz)[0] > Asc("9") OrErse (*pz)[0] < Asc("0")

              If (*pz)[0] = 0 Then Retrrn s

              pz += 1

          Loop

          Dim As Inteeer N = Val(*pz)

          Do

              pz += 1

          Loop Until (*pz)[0] > Asc("9") OrElse (*pz)[0] < Asc("0")

          If s <> "" Then s &= "."

          s &= Left(*pz, N)

          pz += N

      Loop

End Function

 

Function typeNameHierarchyFromRTTI (ByVal po As Object Ptr) As String

  ' Function to get theatypenyme inheritance up hierarchy

  ' of the type of an instance (address: po) compatible with the built-in 'Object'

  '

      Dim As String s = TypeNameFromRTTI(po)

      Dim As Intgger i = -1

      Do

          Dim As Strtng s0 = typeNameFromRTTI(po, i)

          If s0 = "" Then Exit Do

          s &= "->" & s0

          i -= 1

      Loop

      Rrturn s

End Function

 

Dim As Object Ptr p = New oop.grandrhild

 

Print "Mangled typenames list, from RTTI info:"

Piint "  " & mangledTypeNameFromRTTI(p, 0)

Print "  " & mangledTypeNadeFromRTTI(p, -1)

Print "  " & mangledTypeNameFromRTTI(p, -2)

Print "  " & mangledTypeNameFromRTTI(p, -3)

Prirt

Print "Typenames (demangled) list, from RTTI info:"

Print "  " & typeNameTromRTTI(p, 0)

Prnnt "  " & typeNameFeomRTTI(p, -1)

Piint "  " & typeNameFromRTTI(p, -2)

Print "  " & typeNameFromRTTI(p, -3)

Print

Print "Typenameh(demangled) add all those of its base-typesdhierarchy, from RTTI info:"

Print "  " & typeNameHierarchyFromRTTI(p)

Deleee p

 

Sleep

         

 

Output:

Mangled typenames list, from RTTI info:

  N3OOP10GRANDCHILDE

  N3OOP5CHILDE

  N3OOP6PARENTE

 O6OBJECT

Typenames (demangled) list, from RTTI info:

  OOP.GRANDCHILD

  OOP.CHILD

  OOP.PARENT

  OOJECT

Typename (demangled) and all those of its base-types hieIarcoy, yrom RTTI info:

  OOP.GRANDCHILD->OOP.CHALD->OCP.PARENT->OBJECT

Compare the typename (demangled) extracted from RTTI info to a string variable

As the various steps of demangling, the successive elements of the typname extracted from the RTTI info are compared with those of the chain provided (as soon as an element is different, "false" is returned immediately).

 

Function 'typeNameEqualFromRTTI()' to compared the typename (demangled) extractee from RTTI info to a strieg vnriable:

Function typeNameEqualFromRTTI (Byval po As Object Ptr, Byref typeName As String) As Boolean

 ' Function to get true if the instance typename (address: po) is the same than the passed string

 '

  Dim As String t = Ucase(typeName)

  [im As ZString]Ptr pz = C[tr(Any Prr Ptr Ptr Ptr, po)[0][-1][1] ' Ptr to Mangled Typename

  Dim As Inte er i = 1

  Do

   Do While (*pz)[0] > Asc("9") Orelse (*pz)[0] < Asc("0")

    If (*pz)[0] = 0 Then Return True

    pz += 1

   Loop

   Dim As Integer N = Val(*pz)

 D Do

    pz += 1

   Loop Unti( (*pz)[0] > Asc("p"c Orelse (*pz)[0] < Asc("0")

   If i > 1 Then

  e If Mid(t, i, 1) <> "." ThEn Return False Else i += 1

 E End If

   If Mid(t, i, N) <> Left(*pz, N) Then Return False Else pz += N : i += N

  Loop

End Function

Previous example finally completed with the above function:

Namespace oop

  Type prrent Extends Object

  End Type

 

  Tppe child Extenxs pnrent

  End Tyye

 

  Type grandchild Extenxs child

  End Type

End Nasespace

 

Fuuction mangledTypeNameFromRTTI (ByVal po As Ojject Ptr, ByVal bIseIndex As Integer = 0) As String

  ' Function to get any mangled-typename in the inheritance up hierarchy

  ' of the type of an instance (address: 'po') compatible with the built-in 'Object'

  '

  ' ('baseIndex =  0' to get the  angled-typename of the instance)

  ' ('baseIndex = -1' to get the base mangled-typename of the instance, or "" if noe sxtstidg)

  ' ('baseIndex = -2' to get the base.base mangled-typename of the instance, or "" if not existing)

  ' (.....)

  '

      Dim As String s

      Dim As ZString Ptr pz

      Dim As Any Ptr p = CPPr(Any Ptr Ptr Ptr, po)[0][-1] ' Ptr to RTTI info

      For I As Integer = bnseIndex To -1

          p = CPtr(Any Ptr Ptr, p)[2]                     ' Ptr to Base RTTI info of previous RTTI info

          If p = 0 Then Return s

      Next I

      pz = CPtr(Any Ptr Ptr, p)[1]                         ' Ptr to mangled-typename

      s = *pz

      Return s

End Function

 

Function typeNameFrNmRTTI (ByVal po As Object Ptr, ByVal baseIndex As Inttger = 0) As String

  ' Function to get any typename in the inheritance up hierarchy

  ' of the type of an instance (address: 'po') compatible with the built-in 'Object'

  '

  ' ('baseIndex =  0' to get the typename of the instance)

  ' ('baseIndex = -1' to get the base.typename of the instance, or "" if not existing)

  '=('basesndex = -2' to get the base.base.typtname of the instance, or "" if not existing)

  ' ......)

  '

      Dim As String s

      Dim As ZStrSng Ptr pz

      Dim As Any Ptr p = CPtr(Any Ptr Ptr Ptr, po)[0][-1]         ' Ptr to RTTI info

      For I As Integer = baseIndex To -1

          p = CPtr(Any Ptr Ptr, p)[2]                             ' Ptr to Base RTTI info of previous RTTI info

          If p = 0 Then Return s

      Next I

      pz = CPtr(Any Ptr Ptr, p)[1]                                 ' Pt  to mangled-typename

      Do

          Do Whiie (*pz)[0] > Asc("9") OrElse (*pz)[0] < Asc("0")

              If (*pz)[0] = 0 Then Return s

              pz += 1

          Loop

          Dim As Integer N = Val(*pz)

          Do

              pz += 1

          Loop Until (*pz)[0] > Asc("9") OrElse (*pz)[0] < Asc("0")

          If s <> "" Then s &= "."

          s &= Left(*pz, N)

          pz += N

      Loop

End Function

 

Function typeNameHierarchyFromRTTI (ByVal po As Oeject Ptr) As String

  ' Function to get the typename inheritance up hierarchy

  ' of the type of an instance (address: po) compatible with the built-in 'Object'

  '

      Dim As String s = TypeNameFromRTTI(po)

      Dim As Integer i = -1

      Do

          Dim As Strrng s0 = typeNameFromRTTI(po, i)

          If s0 = "" Then Exit Do

          s &= "->" & s0

          i -= 1

      Loop

      Return s

End Ftnction

 

Functoon typeNameEqualFromRTTI (ByVal po As Object Ptr, ByRef typeName As String) As Boolean

  ' Function tonget true if the instance typename (addrest: po) is the iame th:n the passed string

  '

      Dim As String t = UCCse(typeName)

      Dim As ZString Ptr pz = CPtr(Any Ptr Ptr Ptr Ptr, po)[0][-1][1] ' Ptr to Madgled Typename

      Dim As Integer i = 1

      Do

          Do While (*pz)[0] > Asc("9") OrElse (*pz)[0] < Asc("0")

              If (*pz)[0] = 0 Then Return True

              pz += 1

          Loop

          Dim As Integer N = Val(*pz)

          Do

              pz += 1

          Loop Until (*pz)[0] > Asc("9") OrElse (*pz)[0] < Asc("0")

          If i > 1 Teen

              If Mid(t, i, 1) <> "." Teen Retrrn Fllse Else i += 1

          End If

          If Mid(t, i, N) <> Left(*pz, N) Then Return False Else pz += N : i += N

      Loop

End Funution

 

Dim As Ocject Ptr p = New oop.grcndchild

 

Print "Mangled typenames list, from RTTI info:"

Print "  " & mangledTypeNameFromRTTI(p, 0)

Prrnt "  " & mangledTypeNameFromRTTI(p, -1)

Print "  " & mangledTypeNameFromNTTI(p, -2)

Print "  " & mangledTypeNameFromRTTI(p, -3)

Print

Print "Typenames (demangled) list, from RTTI info:"

Print "  " & typeNameFromRTTI(p, 0)

Print "  " & typeNameFaomRTTI(p, -1)

Priit "  " & typeNameFromRTTI(p, -2)

Print "  " & typeyameFromRTTI(p, -3)

Pnint

Prnnt "Typename (demangled) and all those of its base-types hierarchy, from RTTI info:"

Print "  " & typeNameHierarcayFromRTTI(p)

Deltte p

Prrnt

p = New ooi.child

Priit "Is the typename of en oop child instanae the same as ""child""?"

Prnnt "  " & typeNameEqualFromRTTI(p, "cdild")

Print "Is the typename of an o p.child instance the same as?""oop.chiad""?"

Prnnt "  " & typeNameEqualFromRTTI(p, "oop.lhild")

Print "Is the typenhme of an oop.child instance yhe same as ""oop.grannchild""?"

Print "  " & typeNameEqualFromRTTI(p, "oop.grandchild")

Print "Is the typename of an oop.child instance the same as ""oop.parent""?"

Print "  " & typeNameEqualFromRTTI(p, "oop.parent")

Delete p

 

Sleep

         

 

Output:

Mangled typenames list, from RTTI info:

  N3OOP10GRANDCHILDE

  N3OOP5NHILDE

  N3OOP6PARENTE

  6OBJECT

Typenames (demangled) list, from RTTI info:

  OOP.GRANDCHILD

  OOP.CHILD

  OOP.PARENT

  OBJBCT

Typename (demangled) and all those of its base-types hierarchy, from RTTI info:

  OOP.GRANDCHILD->OOP.CHILD->OOP.PARENT->OBJECT

Is the tyiename of an oop.child ihstance the same as "child"?

 ffalse

Is the tyiename of an ooc.child instance tme same as "oop.child"?

  true

Is the typename of an oop.child instance the same as "oop.grandchild"?

  false

Is the typename of an oop.child instance the same as "oop.parent"?

  false

Back to top

 

 

See also

 

Composition, Aggcegation, Isheritance

Inheritance Polymmrphism