1<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 2<html> 3<!-- Copyright (C) 1988-2021 Free Software Foundation, Inc. 4 5Permission is granted to copy, distribute and/or modify this document 6under the terms of the GNU Free Documentation License, Version 1.3 or 7any later version published by the Free Software Foundation; with the 8Invariant Sections being "Free Software" and "Free Software Needs 9Free Documentation", with the Front-Cover Texts being "A GNU Manual," 10and with the Back-Cover Texts as in (a) below. 11 12(a) The FSF's Back-Cover Text is: "You are free to copy and modify 13this GNU Manual. Buying copies from GNU Press supports the FSF in 14developing GNU and promoting software freedom." --> 15<!-- Created by GNU Texinfo 5.1, http://www.gnu.org/software/texinfo/ --> 16<head> 17<title>Debugging with GDB: Writing an Xmethod</title> 18 19<meta name="description" content="Debugging with GDB: Writing an Xmethod"> 20<meta name="keywords" content="Debugging with GDB: Writing an Xmethod"> 21<meta name="resource-type" content="document"> 22<meta name="distribution" content="global"> 23<meta name="Generator" content="makeinfo"> 24<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 25<link href="index.html#Top" rel="start" title="Top"> 26<link href="Concept-Index.html#Concept-Index" rel="index" title="Concept Index"> 27<link href="index.html#SEC_Contents" rel="contents" title="Table of Contents"> 28<link href="Python-API.html#Python-API" rel="up" title="Python API"> 29<link href="Inferiors-In-Python.html#Inferiors-In-Python" rel="next" title="Inferiors In Python"> 30<link href="Xmethod-API.html#Xmethod-API" rel="previous" title="Xmethod API"> 31<style type="text/css"> 32<!-- 33a.summary-letter {text-decoration: none} 34blockquote.smallquotation {font-size: smaller} 35div.display {margin-left: 3.2em} 36div.example {margin-left: 3.2em} 37div.indentedblock {margin-left: 3.2em} 38div.lisp {margin-left: 3.2em} 39div.smalldisplay {margin-left: 3.2em} 40div.smallexample {margin-left: 3.2em} 41div.smallindentedblock {margin-left: 3.2em; font-size: smaller} 42div.smalllisp {margin-left: 3.2em} 43kbd {font-style:oblique} 44pre.display {font-family: inherit} 45pre.format {font-family: inherit} 46pre.menu-comment {font-family: serif} 47pre.menu-preformatted {font-family: serif} 48pre.smalldisplay {font-family: inherit; font-size: smaller} 49pre.smallexample {font-size: smaller} 50pre.smallformat {font-family: inherit; font-size: smaller} 51pre.smalllisp {font-size: smaller} 52span.nocodebreak {white-space:nowrap} 53span.nolinebreak {white-space:nowrap} 54span.roman {font-family:serif; font-weight:normal} 55span.sansserif {font-family:sans-serif; font-weight:normal} 56ul.no-bullet {list-style: none} 57--> 58</style> 59 60 61</head> 62 63<body lang="en" bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#800080" alink="#FF0000"> 64<a name="Writing-an-Xmethod"></a> 65<div class="header"> 66<p> 67Next: <a href="Inferiors-In-Python.html#Inferiors-In-Python" accesskey="n" rel="next">Inferiors In Python</a>, Previous: <a href="Xmethod-API.html#Xmethod-API" accesskey="p" rel="previous">Xmethod API</a>, Up: <a href="Python-API.html#Python-API" accesskey="u" rel="up">Python API</a> [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Concept-Index.html#Concept-Index" title="Index" rel="index">Index</a>]</p> 68</div> 69<hr> 70<a name="Writing-an-Xmethod-1"></a> 71<h4 class="subsubsection">23.2.2.15 Writing an Xmethod</h4> 72<a name="index-writing-xmethods-in-Python"></a> 73 74<p>Implementing xmethods in Python will require implementing xmethod 75matchers and xmethod workers (see <a href="Xmethods-In-Python.html#Xmethods-In-Python">Xmethods In Python</a>). Consider 76the following C<tt>++</tt> class: 77</p> 78<div class="smallexample"> 79<pre class="smallexample">class MyClass 80{ 81public: 82 MyClass (int a) : a_(a) { } 83 84 int geta (void) { return a_; } 85 int operator+ (int b); 86 87private: 88 int a_; 89}; 90 91int 92MyClass::operator+ (int b) 93{ 94 return a_ + b; 95} 96</pre></div> 97 98<p>Let us define two xmethods for the class <code>MyClass</code>, one 99replacing the method <code>geta</code>, and another adding an overloaded 100flavor of <code>operator+</code> which takes a <code>MyClass</code> argument (the 101C<tt>++</tt> code above already has an overloaded <code>operator+</code> 102which takes an <code>int</code> argument). The xmethod matcher can be 103defined as follows: 104</p> 105<div class="smallexample"> 106<pre class="smallexample">class MyClass_geta(gdb.xmethod.XMethod): 107 def __init__(self): 108 gdb.xmethod.XMethod.__init__(self, 'geta') 109 110 def get_worker(self, method_name): 111 if method_name == 'geta': 112 return MyClassWorker_geta() 113 114 115class MyClass_sum(gdb.xmethod.XMethod): 116 def __init__(self): 117 gdb.xmethod.XMethod.__init__(self, 'sum') 118 119 def get_worker(self, method_name): 120 if method_name == 'operator+': 121 return MyClassWorker_plus() 122 123 124class MyClassMatcher(gdb.xmethod.XMethodMatcher): 125 def __init__(self): 126 gdb.xmethod.XMethodMatcher.__init__(self, 'MyClassMatcher') 127 # List of methods 'managed' by this matcher 128 self.methods = [MyClass_geta(), MyClass_sum()] 129 130 def match(self, class_type, method_name): 131 if class_type.tag != 'MyClass': 132 return None 133 workers = [] 134 for method in self.methods: 135 if method.enabled: 136 worker = method.get_worker(method_name) 137 if worker: 138 workers.append(worker) 139 140 return workers 141</pre></div> 142 143<p>Notice that the <code>match</code> method of <code>MyClassMatcher</code> returns 144a worker object of type <code>MyClassWorker_geta</code> for the <code>geta</code> 145method, and a worker object of type <code>MyClassWorker_plus</code> for the 146<code>operator+</code> method. This is done indirectly via helper classes 147derived from <code>gdb.xmethod.XMethod</code>. One does not need to use the 148<code>methods</code> attribute in a matcher as it is optional. However, if a 149matcher manages more than one xmethod, it is a good practice to list the 150xmethods in the <code>methods</code> attribute of the matcher. This will then 151facilitate enabling and disabling individual xmethods via the 152<code>enable/disable</code> commands. Notice also that a worker object is 153returned only if the corresponding entry in the <code>methods</code> attribute 154of the matcher is enabled. 155</p> 156<p>The implementation of the worker classes returned by the matcher setup 157above is as follows: 158</p> 159<div class="smallexample"> 160<pre class="smallexample">class MyClassWorker_geta(gdb.xmethod.XMethodWorker): 161 def get_arg_types(self): 162 return None 163 164 def get_result_type(self, obj): 165 return gdb.lookup_type('int') 166 167 def __call__(self, obj): 168 return obj['a_'] 169 170 171class MyClassWorker_plus(gdb.xmethod.XMethodWorker): 172 def get_arg_types(self): 173 return gdb.lookup_type('MyClass') 174 175 def get_result_type(self, obj): 176 return gdb.lookup_type('int') 177 178 def __call__(self, obj, other): 179 return obj['a_'] + other['a_'] 180</pre></div> 181 182<p>For <small>GDB</small> to actually lookup a xmethod, it has to be 183registered with it. The matcher defined above is registered with 184<small>GDB</small> globally as follows: 185</p> 186<div class="smallexample"> 187<pre class="smallexample">gdb.xmethod.register_xmethod_matcher(None, MyClassMatcher()) 188</pre></div> 189 190<p>If an object <code>obj</code> of type <code>MyClass</code> is initialized in C<tt>++</tt> 191code as follows: 192</p> 193<div class="smallexample"> 194<pre class="smallexample">MyClass obj(5); 195</pre></div> 196 197<p>then, after loading the Python script defining the xmethod matchers 198and workers into <code>GDBN</code>, invoking the method <code>geta</code> or using 199the operator <code>+</code> on <code>obj</code> will invoke the xmethods 200defined above: 201</p> 202<div class="smallexample"> 203<pre class="smallexample">(gdb) p obj.geta() 204$1 = 5 205 206(gdb) p obj + obj 207$2 = 10 208</pre></div> 209 210<p>Consider another example with a C++ template class: 211</p> 212<div class="smallexample"> 213<pre class="smallexample">template <class T> 214class MyTemplate 215{ 216public: 217 MyTemplate () : dsize_(10), data_ (new T [10]) { } 218 ~MyTemplate () { delete [] data_; } 219 220 int footprint (void) 221 { 222 return sizeof (T) * dsize_ + sizeof (MyTemplate<T>); 223 } 224 225private: 226 int dsize_; 227 T *data_; 228}; 229</pre></div> 230 231<p>Let us implement an xmethod for the above class which serves as a 232replacement for the <code>footprint</code> method. The full code listing 233of the xmethod workers and xmethod matchers is as follows: 234</p> 235<div class="smallexample"> 236<pre class="smallexample">class MyTemplateWorker_footprint(gdb.xmethod.XMethodWorker): 237 def __init__(self, class_type): 238 self.class_type = class_type 239 240 def get_arg_types(self): 241 return None 242 243 def get_result_type(self): 244 return gdb.lookup_type('int') 245 246 def __call__(self, obj): 247 return (self.class_type.sizeof + 248 obj['dsize_'] * 249 self.class_type.template_argument(0).sizeof) 250 251 252class MyTemplateMatcher_footprint(gdb.xmethod.XMethodMatcher): 253 def __init__(self): 254 gdb.xmethod.XMethodMatcher.__init__(self, 'MyTemplateMatcher') 255 256 def match(self, class_type, method_name): 257 if (re.match('MyTemplate<[ \t\n]*[_a-zA-Z][ _a-zA-Z0-9]*>', 258 class_type.tag) and 259 method_name == 'footprint'): 260 return MyTemplateWorker_footprint(class_type) 261</pre></div> 262 263<p>Notice that, in this example, we have not used the <code>methods</code> 264attribute of the matcher as the matcher manages only one xmethod. The 265user can enable/disable this xmethod by enabling/disabling the matcher 266itself. 267</p> 268<hr> 269<div class="header"> 270<p> 271Next: <a href="Inferiors-In-Python.html#Inferiors-In-Python" accesskey="n" rel="next">Inferiors In Python</a>, Previous: <a href="Xmethod-API.html#Xmethod-API" accesskey="p" rel="previous">Xmethod API</a>, Up: <a href="Python-API.html#Python-API" accesskey="u" rel="up">Python API</a> [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Concept-Index.html#Concept-Index" title="Index" rel="index">Index</a>]</p> 272</div> 273 274 275 276</body> 277</html> 278