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.
fxm
Posts: 9021
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

Postby fxm » May 19, 2019 11:58

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, vtabl (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)      |       | Length |
       .-------------------.       |-------------------|       |-----------------------|       | (ASCII)|
    [0]| vptr: Ptr to vtbl |--->[0]|Ptr to virt proc #1|   [+1]|Ptr to Mangled Typename|--->[0]|    &   |
       |-------------------|       |-------------------|       |-----------------------|       |Typename|
       |UDT member field #a|   [+1]|Ptr to virt proc #2|   [+2]| Ptr to Base RTTI info |---.   | (ASCII)|
       |-------------------|       |-------------------|       |_______________________|   |   |________|
       |UDT member field #b|   [+2]|Ptr to virt proc #3|   ________________________________|
       |-------------------|       :- - - - - - - - - -:  |
       |UDT member field #c|       :                   :  |             Base RTTI info
       :- - - - - - - - - -:       :                   :  |       .----------------------------.
       :                   :       |___________________|  '--->[0]|        reserved (0)        |
       :                   :                                      |----------------------------|
       |___________________|                                  [+1]|Ptr to Mangled Base Typename|--->
                                                                  |----------------------------|
                                                              [+2]| Ptr to Base.Base RTTI info |---.
                                                                  |____________________________|   |
                                                                                                   |
                                                                                                   V
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
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 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
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
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
Last edited by fxm on Jun 16, 2019 6:29, edited 4 times in total.
Reason: Paragraph 6 added.
SARG
Posts: 901
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

Postby SARG » May 19, 2019 16:49

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: 72
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

Postby Xusinboy Bekchanov » May 19, 2019 16:50

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
Posts: 9021
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

Postby fxm » May 19, 2019 17:52

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
Posts: 9021
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

Postby fxm » May 19, 2019 17:54

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

No.

Return to “Documentation”

Who is online

Users browsing this forum: No registered users and 1 guest