Visual Studio natvis displaying pointer-to-interface

0

I'm trying to create debug visualizers for our company custom smart pointers. I would like to use ExpandItem to get the contents just one level down, which works for concrete types like ref_ptr<Vector2d>, but not for virtual types like ref_ptr<IStreamManager>. When using the virtual types, I get two entries, one for the underlying type, which I can then expand, and one for the __vfptr.

What I'm getting:

v streamManagerPtr         shared_ptr { count=35, ptr=... }
    [Reference Count]      2
  v [StreamMgr]            {...}
      m_resourceMgr        shared_ptr { count=35, ptr=... }
      m_fileMgr            shared_ptr { count=23, ptr=... }
      ...
  > __vfptr                0xdeadbeef
  > [Raw View]             {...}

What I want:

v streamManagerPtr         shared_ptr { count=35, ptr=... }
    [Reference Count]      2
    m_resourceMgr          shared_ptr { count=35, ptr=... }
    m_fileMgr              shared_ptr { count=23, ptr=... }
    ...
  > [Raw View]             {...}

Is there any way to bring the contents of the underlying dynamic type up one more level so I don't have to deal with this useless level of nesting?

visual-studio
debuggervisualizer
natvis
asked on Stack Overflow May 30, 2017 by porglezomp

2 Answers

0

I believe you can use something like this:

<Type Name="shared_ptr&lt;*&gt;">
  <Expand>
    <ExpandedItem Condition="ptr != 0">*ptr</ExpandedItem>
  </Expand>
</Type>

The ExpandedItem tag basically removes a level of nesting, displaying the contents of the item in the tag as though they were regular items at the same nesting level as the rest of the Items in the Expand tag.

answered on Stack Overflow Aug 30, 2017 by PfhorSlayer
0

I am not using ref_ptr, so I tested with my own template class. So please be mercy if the following code might not immediately work with ref_ptr.

<Type Name="ref_ptr&lt;*&gt;" Priority="MediumLow">
  <Expand>
    <ExpandedItem Condition="_ptr->__vfptr">*_ptr</ExpandedItem>
  </Expand>
</Type>
<Type Name="ref_ptr&lt;*&gt;">
  <Expand>
    <ExpandedItem>_ptr</ExpandedItem>
  </Expand>
</Type>

The trick is descibed on MSDN: natvis tries to parse the first entry. That one is checking if _ptr->__vfptr is not nullptr. For your IStreamManager this can be parsed and evaluates to true, so the first entry is used, the object itself is taken and expanded. If the condition on the first entry fails to parse because there is no __vfptr then the first entry is not used and the second entry is used. That one is doing just what you have now in your existing code.

answered on Stack Overflow Nov 11, 2018 by Werner Henze • edited May 9, 2020 by Werner Henze

User contributions licensed under CC BY-SA 3.0