
In RAD Studio 10.2.1 we added support for debug visualizers for Delphi generic and C++ template types. A debug visualizer is an IDE plugin that allows you to change the display of a variable in the various debug windows, such as Local Variables and Watches.
“Great!”, you may think, “but how do I actually write one of these visualizers?”
Pretty easily, as it turns out.
A debug vizualiser is an interfaced class that implements some specific Open Tools API interfaces (see toolsapi.pas), located in a DLL or package, and an instance of which is registered with the IDE when the package is loaded. Those interfaces are:
- IOTADebuggerVisualizer, IOTADebuggerVisualizer250: name and description of the visualizer, list of types it’s interested in; version 250 adds support for generics or templates by allowing you to specify that a type string is for a generic or template type.
- IOTADebuggerVisualizerValueReplacer: this lets you replace the result of an expression returned by the debug evaluator with some other content – whatever you want. You can get more advanced than this, such as showing an external window for the results. This is just a simple example.
- IOTAThreadNotifier, IOTAThreadNotifier160: let you handle an evaluation completing. A notifier, by convention in the ToolsAPI, also always has four other methods to do with saving, destroying and modification that are not meaningful in this example.
Table of Contents
Generic and template debug visualizer example
Here’s a complete visualizer code snippet. To test this out, create a new package, and add designide to the Requires. Then add a unit called GenericVisualizer.pas to it and paste in the following source code. To test it out, just right-click and Install, and then it’s running right there inside your local IDE instance. (You can also debug the IDE with IDE if you want to do some more advanced work and load it while debugging an instance of the IDE with your first copy of the IDE.)
Source code
To test
For Delphi
Define some types:
This example is longer than the C++ one, because it demonstrates both generic classes and interfaces. It also shows some descendant types, where you need to register the descendant type separately. (For a non-generic-type debug visualizer, the visualizer is called for descendants of the registered type automatically.)
And create a new console app, giving it the contents:
For C++
Create a new console app (and some shiny new template types as well, if you wish) and give it the contents:
To extend
This is the exciting bit! Try changing the data returned from GetReplacementValue(), and also try evaluating expressions yourself in the visualizer to use in the returned replacement.
Have fun!
Design. Code. Compile. Deploy.
Start Free Trial Upgrade Today
Free Delphi Community Edition Free C++Builder Community Edition
Visualization of STL types is paramount to debugging. Inability to inspect simple things like std::vector has frustrated me for years. If this mechanism enables such inspection options, I would highly suggest to integrate this with the IDE, for as many STL types as possible!
For C++builder users without Delphi license, can this be used?
Hi Frank,
We’ve actually replaced this system in 10.4, for the C++ Win64 debugger, and it works even better! You can read about it here: https://blogs.embarcadero.com/new-in-c-builder-10-4-a-new-debugger-for-win64-c/
The new Win64 debugger uses ‘formatters’ which are build into the debugger itself, rather than being a plugin in the IDE, as this post describes. It includes formatters for std::vector, as well as eight or nine other types, and we’ve added a couple more since then. You can also easily add your own data types too, eg if you have your own complex data structure.
And yes, both the system in this post, and the new system in 10.4.x, can be used with standalone C++Builder. We have a beta for 10.4.2 right now for active update subscription customers and if you’re interested, I recommend you try that out.
This is not working in Delphi 12.
There is a bug in the example:
procedure EvaluteComplete(const ExprStr: string; const ResultStr: string;
CanModify: Boolean; ResultAddress: Cardinal; ResultSize: Cardinal;
ReturnCode: Integer);
There is no procedure ´EvaluteComplete´. If it should be
EvaluateComplete
, “overload” is missing in the declaration.Hello — that is a good catch! This article was written in 2017. At some point since then, and I’m afraid I cannot remember the exact year, we fixed that typo. We don’t normally update fixed interfaces but a spelling error seemed worthwhile. If you’re using the latest version, you should hopefully see it as “Evaluate”, and the methods should be overloaded correctly. Re the last point, they’re not?
Thanks for letting us know Roland. I’ve corrected the typo; I appreciate you pointing it out. The blogging platform we currently use means code examples are pasted in or typed manually and that can occasionally lead to some errors.
WRG to it working on RAD Studio 12 – there are many thousands of articles most of which have code examples in them. As a result it’s not really practical or possible to go through each older article and update the code to work with new versions of the IDE. Most work (one of the benefits of Delphi is its backward compatibility), this one seems to need some work though. It’s a pretty elderly article from 2017! 🙂