Next: Inferiors In Python, Previous: Selecting Pretty-Printers, Up: Python API
A pretty-printer consists of two parts: a lookup function to detect if the type is supported, and the printer itself.
Here is an example showing how a
std::string printer might be
written. See Pretty Printing API, for details on the API this class
must provide.
class StdStringPrinter(object): "Print a std::string" def __init__(self, val): self.val = val def to_string(self): return self.val['_M_dataplus']['_M_p'] def display_hint(self): return 'string'
And here is an example showing how a lookup function for the printer example above might be written.
def str_lookup_function(val): lookup_tag = val.type.tag if lookup_tag == None: return None regex = re.compile("^std::basic_string<char,.*>$") if regex.match(lookup_tag): return StdStringPrinter(val) return None
The example lookup function extracts the value's type, and attempts to
match it to a type that it can pretty-print. If it is a type the
printer can pretty-print, it will return a printer object. If not, it
returns
None.
We recommend that you put your core pretty-printers into a Python Python
std::string example (see Pretty Printing API),
this code might appear in
gdb.libstdcxx.v6:
def register_printers(objfile): objfile.pretty_printers.append(str_lookup_function)
And then the corresponding contents of the auto-load file would be:
import gdb.libstdcxx.v6 gdb.libstdcxx.v6.register_printers(gdb.current_objfile())
The previous example illustrates a basic pretty-printer. There are a few things that can be improved on. The printer doesn't have a name, making it hard to identify in a list of installed printers. The lookup function has a name, but lookup functions can have arbitrary, even identical, names.
Second, these
problems (see gdb.printing).
Here is another example that handles multiple types.
These are the types we are going to pretty-print:
struct foo { int a, b; }; struct bar { struct foo x, y; };
Here are the printers:
class fooPrinter: """Print a foo object.""" def __init__(self, val): self.val = val def to_string(self): return ("a=<" + str(self.val["a"]) + "> b=<" + str(self.val["b"]) + ">") class barPrinter: """Print a bar object.""" def __init__(self, val): self.val = val def to_string(self): return ("x=<" + str(self.val["x"]) + "> y=<" + str(self.val["y"]) + ">")
This example doesn't need a lookup function, that is handled by the
gdb.printing module. Instead a function is provided to build up
the object that handles the lookup.
import gdb.printing def build_pretty_printer(): pp = gdb.printing.RegexpCollectionPrettyPrinter( "my_library") pp.add_printer('foo', '^foo$', fooPrinter) pp.add_printer('bar', '^bar$', barPrinter) return pp
And here is the autoload support:
import gdb.printing import my_library gdb.printing.register_pretty_printer( gdb.current_objfile(), my_library.build_pretty_printer())
Finally, when this printer is loaded into gdb, here is the corresponding output of `info pretty-printer':
(gdb) info pretty-printer my_library.so: my_library foo bar