How using RTTI from FB built-in OBJECT to extract Typename and those of all Bases of an instance

Forum for discussion about the documentation project.
Post Reply
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

How using RTTI from FB built-in OBJECT to extract Typename and those of all Bases of an instance

Post by fxm »

The Object built-in type provides the RTTI capacity for all types derived from it using the Extends declaration. The RTTI capacity allows to determine the real type of an object at runtime, which can be different of its at compile-time.
The operator Is (Run-Time Type Information) uses it to check if an object is compatible to a type derived from its compile-time type, because RTTI provides not only the runtime typename of the object but also all typenames of its base types, up to the Object built-in type.
The stored typenames by RTTI are mangled names. Some C++ implementations produce a human-readable typename. Others, most notably gcc, return the mangled name (convertible to human-readable form using implementation-specific API). But FreeBASIC returns nothing.
The aim of this article is to provide a description of the RTTI structure, and to propose user procedures to extract the typenames (mangled and also demangled).

1) How are chained the entities: object instance, vptr, vtbl (vtable), and RTTI info
  • Instance -> Vptr -> Vtbl(Vtable) -> RTTI info chaining:
    • For any type derived (directly or indirectly) from the Object built-in type, a hidden pointer 'vptr' is added at beginning (located at offset 0) of its data fields (own or inherited). This vptr points to the virtual table (vtbl or vtable) of the considered type.
    • 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 RunTime Type Information (RTTI) info block of the considered type.
    • The RTTI info block contains (located at offset +1) a pointer to the mangled-typename of the considered type (ascii characters). The RTTI info block also contains (located at offset +2) a pointer to the RTTI info block of its Base. All RTTI info blocks for up-hierarchy are so chained.
  • Instance -> Vptr -> Vtbl(Vtable) -> RTTI info diagram:

    Code: Select all

                                       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|   [+2]|Ptr to virt proc #3|   ________________________________|   |each component |
       |-------------------|       :- - - - - - - - - -:  |                                    |_______________|
       |UDT member field #c|       :                   :  |             Base RTTI info
       :- - - - - - - - - -:       :                   :  |       .----------------------------.
       :                   :       |___________________|  '--->[0]|        reserved (0)        |
       :                   :                                      |----------------------------|
       |___________________|                                  [+1]|Ptr to Mangled Base Typename|--->
                                                                  |----------------------------|
                                                              [+2]| Ptr to Base.Base RTTI info |---.
                                                                  |____________________________|   |
                                                                                                   |
                                                                                                   V
    [/b]
2) How to extract the mangled typenames from RTTI info
  • Extraction of the mangled typename from the RTTI info:
    • From the instance address, the RTTI info pointer of the type of the instance is accessed through a double indirection (with 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:

    Code: Select all

    Function mangledTypeNameFromRTTI (Byval po As Object Ptr, Byval baseIndex 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 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 = 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
        Return s
    End Function
    
  • Example of mangled typenames extraction from RTTI info, for an inheritance structure (three derived level) declared inside a namespace block:

    Code: Select all

    Namespace oop
      Type parent Extends Object
      End Type
      
      Type child Extends parent
      End Type
      
      Type grandchild Extends child
      End Type
    End namespace
    
    Function mangledTypeNameFromRTTI (Byval po As Object Ptr, Byval baseIndex 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 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 = 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
        Return s
    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)
    Delete p
    
    Sleep
    

    Code: Select all

    Mangled typenames list, from RTTI info:
      N3OOP10GRANDCHILDE
      N3OOP5CHILDE
      N3OOP6PARENTE
      6OBJECT
    [/b]
3) How the mangling of the typenames is implemented
  • From the above outputs, the mangling process on typenames can be highlighted with the following formatting:
    • N3OOP10GRANDCHILDE
      (for 'oop.grandchild')

      N3OOP5CHILDE
      (for 'oop.child')

      N3OOP6PARENTE
      (for 'oop.parent')

      6OBJECT
      (for 'Object')
    • Details on the the mangling process on typenames in the RTTI info:
      - The mangled typename is a Zstring (ended by the null character).
      - Each component (one dot as separator) of the full typename (converted to uppercase) is preceded by its number of characters encoded in ASCII itself (based on length-prefixed strings).
      - When the type is inside at least one namespace, the mangled typename string begins with an additional "N" and ends with an additional "E".
      • (prefix "N" and suffix "E" from nested-name ... ending)
4) How to extract the typenames (demangled) from RTTI info
  • The previous function ('mangledTypeNameFromRTTI()') can be now completed with a demangling process.
  • Function 'typeNameFromRTTI()' to extract the demangled typenames:

    Code: Select all

    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 =  0' to get the typename 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 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
        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
    
  • Previous example completed with the above function:

    Code: Select all

    Namespace oop
      Type parent Extends Object
      End Type
      
      Type child Extends parent
      End Type
      
      Type grandchild Extends child
      End Type
    End namespace
    
    Function mangledTypeNameFromRTTI (Byval po As Object Ptr, Byval baseIndex 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 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 = 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
        Return s
    End Function
    
    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 =  0' to get the typename 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 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
        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
    
    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)
    Print "  " & typeNameFromRTTI(p, -1)
    Print "  " & typeNameFromRTTI(p, -2)
    Print "  " & typeNameFromRTTI(p, -3)
    Delete p
    
    Sleep
    

    Code: Select all

    Mangled typenames list, from RTTI info:
      N3OOP10GRANDCHILDE
      N3OOP5CHILDE
      N3OOP6PARENTE
      6OBJECT
    
    Typenames (demangled) list, from RTTI info:
      OOP.GRANDCHILD
      OOP.CHILD
      OOP.PARENT
      OBJECT
    [/b]
5) How to 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 'baseIndex' (from the value 0) and to stop it as soon as an empty string is returned. Finaly by returning a string containing the different typenames with a hierarchic separator between each.
  • Function 'typeNameHierarchyFromRTTI()' to extract the Typename (demangled) and all those of its base-types hierarchy:

    Code: Select all

    Function typeNameHierarchyFromRTTI (Byval po As Object 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 String s0 = typeNameFromRTTI(po, i)
          If s0 = "" Then Exit Do
          s &= "->" & s0
          i -= 1
        Loop
        Return s
    End Function
    
  • Previous example again completed with the above function:

    Code: Select all

    Namespace oop
      Type parent Extends Object
      End Type
      
      Type child Extends parent
      End Type
      
      Type grandchild Extends child
      End Type
    End namespace
    
    Function mangledTypeNameFromRTTI (Byval po As Object Ptr, Byval baseIndex 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 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 = 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
        Return s
    End Function
    
    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 =  0' to get the typename 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 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
        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
    
    Function typeNameHierarchyFromRTTI (Byval po As Object 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 String s0 = typeNameFromRTTI(po, i)
          If s0 = "" Then Exit Do
          s &= "->" & s0
          i -= 1
        Loop
        Return s
    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)
    Print "  " & typeNameFromRTTI(p, -1)
    Print "  " & typeNameFromRTTI(p, -2)
    Print "  " & typeNameFromRTTI(p, -3)
    Print
    Print "Typename (demangled) and all those of its base-types hierarchy, from RTTI info:"
    Print "  " & typeNameHierarchyFromRTTI(p)
    Delete p
    
    Sleep
    

    Code: Select all

    Mangled typenames list, from RTTI info:
      N3OOP10GRANDCHILDE
      N3OOP5CHILDE
      N3OOP6PARENTE
      6OBJECT
    
    Typenames (demangled) list, from RTTI info:
      OOP.GRANDCHILD
      OOP.CHILD
      OOP.PARENT
      OBJECT
    
    Typename (demangled) and all those of its base-types hierarchy, from RTTI info:
      OOP.GRANDCHILD->OOP.CHILD->OOP.PARENT->OBJECT
    [/b]
6) How to 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) extracted from RTTI info to a string variable:

    Code: Select all

    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)
        Dim As ZString Ptr pz = Cptr(Any Ptr Ptr Ptr Ptr, po)[0][-1][1] ' Ptr to Mangled 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 Then
            If Mid(t, i, 1) <> "." Then Return False Else i += 1
          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:

    Code: Select all

    Namespace oop
      Type parent Extends Object
      End Type
     
      Type child Extends parent
      End Type
     
      Type grandchild Extends child
      End Type
    End namespace
    
    Function mangledTypeNameFromRTTI (Byval po As Object Ptr, Byval baseIndex 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 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 = 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
        Return s
    End Function
    
    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 =  0' to get the typename 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 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
        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
    
    Function typeNameHierarchyFromRTTI (Byval po As Object 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 String s0 = typeNameFromRTTI(po, i)
          If s0 = "" Then Exit Do
          s &= "->" & s0
          i -= 1
        Loop
        Return s
    End Function
    
    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)
        Dim As ZString Ptr pz = Cptr(Any Ptr Ptr Ptr Ptr, po)[0][-1][1] ' Ptr to Mangled 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 Then
            If Mid(t, i, 1) <> "." Then Return False Else i += 1
          End If
          If Mid(t, i, N) <> Left(*pz, N) Then Return False Else pz += N : i += 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)
    Print "  " & typeNameFromRTTI(p, -1)
    Print "  " & typeNameFromRTTI(p, -2)
    Print "  " & typeNameFromRTTI(p, -3)
    Print
    Print "Typename (demangled) and all those of its base-types hierarchy, from RTTI info:"
    Print "  " & typeNameHierarchyFromRTTI(p)
    Delete p
    Print
    p = New oop.child
    Print "Is the typename of an oop.child instance the same as ""child""?"
    Print "  " & typeNameEqualFromRTTI(p, "child")
    Print "Is the typename of an oop.child instance the same as ""oop.child""?"
    Print "  " & typeNameEqualFromRTTI(p, "oop.child")
    Print "Is the typename of an oop.child instance the same as ""oop.grandchild""?"
    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
    

    Code: Select all

    Mangled typenames list, from RTTI info:
      N3OOP10GRANDCHILDE
      N3OOP5CHILDE
      N3OOP6PARENTE
      6OBJECT
    
    Typenames (demangled) list, from RTTI info:
      OOP.GRANDCHILD
      OOP.CHILD
      OOP.PARENT
      OBJECT
    
    Typename (demangled) and all those of its base-types hierarchy, from RTTI info:
      OOP.GRANDCHILD->OOP.CHILD->OOP.PARENT->OBJECT
    
    Is the typename of an oop.child instance the same as "child"?
      false
    Is the typename of an oop.child instance the 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
    [/b]
Last edited by fxm on Jun 16, 2019 6:29, edited 4 times in total.
SARG
Posts: 1765
Joined: May 27, 2005 7:15
Location: FRANCE

Re: How using RTTI from FB built-in OBJECT to extract Typename and those of all Bases of an instance

Post by SARG »

Hi fxm,
Is the prefix "N" and the suffix "E" from namespace ?
N for nested-name and E for ending the sequence.

Extract from a precious doc I use for demangling variable or procedure names in FBdebugger :

"Names of objects nested in namespaces or classes are identified as a delimited sequence of names identifying the enclosing scopes. In addition, when naming a class member function, CV-qualifiers may be prefixed to the compound name, encoding the this attributes. Note that if member function CV-qualifiers are required, the delimited form must be used even if the remainder of the name is a single substitution.

<nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
::= N [<CV-qualifiers>] <template-prefix> <template-args> E"

I could upload the entire doc if you are interested.
Xusinboy Bekchanov
Posts: 789
Joined: Jul 26, 2018 18:28

Re: How using RTTI from FB built-in OBJECT to extract Typename and those of all Bases of an instance

Post by Xusinboy Bekchanov »

Thank you, I was looking for this opportunity a lot. Maybe i use it in mff. Is it possible to find the class names in the original case (mixed case)?
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: How using RTTI from FB built-in OBJECT to extract Typename and those of all Bases of an instance

Post by fxm »

SARG wrote:Hi fxm,
Is the prefix "N" and the suffix "E" from namespace ?
N for nested-name and E for ending the sequence.
Thanks.
I updated my article.
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: How using RTTI from FB built-in OBJECT to extract Typename and those of all Bases of an instance

Post by fxm »

Xusinboy Bekchanov wrote:Is it possible to find the class names in the original case (mixed case)?
No.
Post Reply