Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / tools / src / nas,5.n2.os.2 / lib / python / html / python / ext / node23.html
CommitLineData
86530b38
AT
1<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
2<html>
3<head>
4<link rel="STYLESHEET" href="ext.css" type='text/css' />
5<link rel="SHORTCUT ICON" href="../icons/pyfav.png" type="image/png" />
6<link rel='start' href='../index.html' title='Python Documentation Index' />
7<link rel="first" href="ext.html" title='Extending and Embedding the Python Interpreter' />
8<link rel='contents' href='contents.html' title="Contents" />
9<link rel='last' href='about.html' title='About this document...' />
10<link rel='help' href='about.html' title='About this document...' />
11<link rel="next" href="node24.html" />
12<link rel="prev" href="node22.html" />
13<link rel="parent" href="dnt-basics.html" />
14<link rel="next" href="node24.html" />
15<meta name='aesop' content='information' />
16<title>2.1.2 Providing finer control over data attributes</title>
17</head>
18<body>
19<DIV CLASS="navigation">
20<div id='top-navigation-panel' xml:id='top-navigation-panel'>
21<table align="center" width="100%" cellpadding="0" cellspacing="2">
22<tr>
23<td class='online-navigation'><a rel="prev" title="2.1.1 Adding data and"
24 href="node22.html"><img src='../icons/previous.png'
25 border='0' height='32' alt='Previous Page' width='32' /></A></td>
26<td class='online-navigation'><a rel="parent" title="2.1 The Basics"
27 href="dnt-basics.html"><img src='../icons/up.png'
28 border='0' height='32' alt='Up One Level' width='32' /></A></td>
29<td class='online-navigation'><a rel="next" title="2.1.3 Supporting cyclic garbage"
30 href="node24.html"><img src='../icons/next.png'
31 border='0' height='32' alt='Next Page' width='32' /></A></td>
32<td align="center" width="100%">Extending and Embedding the Python Interpreter</td>
33<td class='online-navigation'><a rel="contents" title="Table of Contents"
34 href="contents.html"><img src='../icons/contents.png'
35 border='0' height='32' alt='Contents' width='32' /></A></td>
36<td class='online-navigation'><img src='../icons/blank.png'
37 border='0' height='32' alt='' width='32' /></td>
38<td class='online-navigation'><img src='../icons/blank.png'
39 border='0' height='32' alt='' width='32' /></td>
40</tr></table>
41<div class='online-navigation'>
42<b class="navlabel">Previous:</b>
43<a class="sectref" rel="prev" href="node22.html">2.1.1 Adding data and</A>
44<b class="navlabel">Up:</b>
45<a class="sectref" rel="parent" href="dnt-basics.html">2.1 The Basics</A>
46<b class="navlabel">Next:</b>
47<a class="sectref" rel="next" href="node24.html">2.1.3 Supporting cyclic garbage</A>
48</div>
49<hr /></div>
50</DIV>
51<!--End of Navigation Panel-->
52
53<H2><A NAME="SECTION004120000000000000000">
542.1.2 Providing finer control over data attributes</A>
55</H2>
56
57<P>
58In this section, we'll provide finer control over how the
59<tt class="member">first</tt> and <tt class="member">last</tt> attributes are set in the
60<tt class="class">Noddy</tt> example. In the previous version of our module, the
61instance variables <tt class="member">first</tt> and <tt class="member">last</tt> could be set to
62non-string values or even deleted. We want to make sure that these
63attributes always contain strings.
64
65<P>
66<div class="verbatim">
67<pre>#include &lt;Python.h&gt;
68#include "structmember.h"
69
70typedef struct {
71 PyObject_HEAD
72 PyObject *first;
73 PyObject *last;
74 int number;
75} Noddy;
76
77static void
78Noddy_dealloc(Noddy* self)
79{
80 Py_XDECREF(self-&gt;first);
81 Py_XDECREF(self-&gt;last);
82 self-&gt;ob_type-&gt;tp_free((PyObject*)self);
83}
84
85static PyObject *
86Noddy_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
87{
88 Noddy *self;
89
90 self = (Noddy *)type-&gt;tp_alloc(type, 0);
91 if (self != NULL) {
92 self-&gt;first = PyString_FromString("");
93 if (self-&gt;first == NULL)
94 {
95 Py_DECREF(self);
96 return NULL;
97 }
98
99 self-&gt;last = PyString_FromString("");
100 if (self-&gt;last == NULL)
101 {
102 Py_DECREF(self);
103 return NULL;
104 }
105
106 self-&gt;number = 0;
107 }
108
109 return (PyObject *)self;
110}
111
112static int
113Noddy_init(Noddy *self, PyObject *args, PyObject *kwds)
114{
115 PyObject *first=NULL, *last=NULL, *tmp;
116
117 static char *kwlist[] = {"first", "last", "number", NULL};
118
119 if (! PyArg_ParseTupleAndKeywords(args, kwds, "|SSi", kwlist,
120 &amp;first, &amp;last,
121 &amp;self-&gt;number))
122 return -1;
123
124 if (first) {
125 tmp = self-&gt;first;
126 Py_INCREF(first);
127 self-&gt;first = first;
128 Py_DECREF(tmp);
129 }
130
131 if (last) {
132 tmp = self-&gt;last;
133 Py_INCREF(last);
134 self-&gt;last = last;
135 Py_DECREF(tmp);
136 }
137
138 return 0;
139}
140
141static PyMemberDef Noddy_members[] = {
142 {"number", T_INT, offsetof(Noddy, number), 0,
143 "noddy number"},
144 {NULL} /* Sentinel */
145};
146
147static PyObject *
148Noddy_getfirst(Noddy *self, void *closure)
149{
150 Py_INCREF(self-&gt;first);
151 return self-&gt;first;
152}
153
154static int
155Noddy_setfirst(Noddy *self, PyObject *value, void *closure)
156{
157 if (value == NULL) {
158 PyErr_SetString(PyExc_TypeError, "Cannot delete the first attribute");
159 return -1;
160 }
161
162 if (! PyString_Check(value)) {
163 PyErr_SetString(PyExc_TypeError,
164 "The first attribute value must be a string");
165 return -1;
166 }
167
168 Py_DECREF(self-&gt;first);
169 Py_INCREF(value);
170 self-&gt;first = value;
171
172 return 0;
173}
174
175static PyObject *
176Noddy_getlast(Noddy *self, void *closure)
177{
178 Py_INCREF(self-&gt;last);
179 return self-&gt;last;
180}
181
182static int
183Noddy_setlast(Noddy *self, PyObject *value, void *closure)
184{
185 if (value == NULL) {
186 PyErr_SetString(PyExc_TypeError, "Cannot delete the last attribute");
187 return -1;
188 }
189
190 if (! PyString_Check(value)) {
191 PyErr_SetString(PyExc_TypeError,
192 "The last attribute value must be a string");
193 return -1;
194 }
195
196 Py_DECREF(self-&gt;last);
197 Py_INCREF(value);
198 self-&gt;last = value;
199
200 return 0;
201}
202
203static PyGetSetDef Noddy_getseters[] = {
204 {"first",
205 (getter)Noddy_getfirst, (setter)Noddy_setfirst,
206 "first name",
207 NULL},
208 {"last",
209 (getter)Noddy_getlast, (setter)Noddy_setlast,
210 "last name",
211 NULL},
212 {NULL} /* Sentinel */
213};
214
215static PyObject *
216Noddy_name(Noddy* self)
217{
218 static PyObject *format = NULL;
219 PyObject *args, *result;
220
221 if (format == NULL) {
222 format = PyString_FromString("%s %s");
223 if (format == NULL)
224 return NULL;
225 }
226
227 args = Py_BuildValue("OO", self-&gt;first, self-&gt;last);
228 if (args == NULL)
229 return NULL;
230
231 result = PyString_Format(format, args);
232 Py_DECREF(args);
233
234 return result;
235}
236
237static PyMethodDef Noddy_methods[] = {
238 {"name", (PyCFunction)Noddy_name, METH_NOARGS,
239 "Return the name, combining the first and last name"
240 },
241 {NULL} /* Sentinel */
242};
243
244static PyTypeObject NoddyType = {
245 PyObject_HEAD_INIT(NULL)
246 0, /*ob_size*/
247 "noddy.Noddy", /*tp_name*/
248 sizeof(Noddy), /*tp_basicsize*/
249 0, /*tp_itemsize*/
250 (destructor)Noddy_dealloc, /*tp_dealloc*/
251 0, /*tp_print*/
252 0, /*tp_getattr*/
253 0, /*tp_setattr*/
254 0, /*tp_compare*/
255 0, /*tp_repr*/
256 0, /*tp_as_number*/
257 0, /*tp_as_sequence*/
258 0, /*tp_as_mapping*/
259 0, /*tp_hash */
260 0, /*tp_call*/
261 0, /*tp_str*/
262 0, /*tp_getattro*/
263 0, /*tp_setattro*/
264 0, /*tp_as_buffer*/
265 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
266 "Noddy objects", /* tp_doc */
267 0, /* tp_traverse */
268 0, /* tp_clear */
269 0, /* tp_richcompare */
270 0, /* tp_weaklistoffset */
271 0, /* tp_iter */
272 0, /* tp_iternext */
273 Noddy_methods, /* tp_methods */
274 Noddy_members, /* tp_members */
275 Noddy_getseters, /* tp_getset */
276 0, /* tp_base */
277 0, /* tp_dict */
278 0, /* tp_descr_get */
279 0, /* tp_descr_set */
280 0, /* tp_dictoffset */
281 (initproc)Noddy_init, /* tp_init */
282 0, /* tp_alloc */
283 Noddy_new, /* tp_new */
284};
285
286static PyMethodDef module_methods[] = {
287 {NULL} /* Sentinel */
288};
289
290#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
291#define PyMODINIT_FUNC void
292#endif
293PyMODINIT_FUNC
294initnoddy3(void)
295{
296 PyObject* m;
297
298 if (PyType_Ready(&amp;NoddyType) &lt; 0)
299 return;
300
301 m = Py_InitModule3("noddy3", module_methods,
302 "Example module that creates an extension type.");
303
304 if (m == NULL)
305 return;
306
307 Py_INCREF(&amp;NoddyType);
308 PyModule_AddObject(m, "Noddy", (PyObject *)&amp;NoddyType);
309}
310</pre>
311<div class="footer">
312<a href="noddy3.txt" type="text/plain">Download as text (original file name: <span class="file">noddy3.c</span>).</a>
313</div></div>
314
315<P>
316To provide greater control, over the <tt class="member">first</tt> and <tt class="member">last</tt>
317attributes, we'll use custom getter and setter functions. Here are
318the functions for getting and setting the <tt class="member">first</tt> attribute:
319
320<P>
321<div class="verbatim"><pre>
322Noddy_getfirst(Noddy *self, void *closure)
323{
324 Py_INCREF(self-&gt;first);
325 return self-&gt;first;
326}
327
328static int
329Noddy_setfirst(Noddy *self, PyObject *value, void *closure)
330{
331 if (value == NULL) {
332 PyErr_SetString(PyExc_TypeError, "Cannot delete the first attribute");
333 return -1;
334 }
335
336 if (! PyString_Check(value)) {
337 PyErr_SetString(PyExc_TypeError,
338 "The first attribute value must be a string");
339 return -1;
340 }
341
342 Py_DECREF(self-&gt;first);
343 Py_INCREF(value);
344 self-&gt;first = value;
345
346 return 0;
347}
348</pre></div>
349
350<P>
351The getter function is passed a <tt class="class">Noddy</tt> object and a
352``closure'', which is void pointer. In this case, the closure is
353ignored. (The closure supports an advanced usage in which definition
354data is passed to the getter and setter. This could, for example, be
355used to allow a single set of getter and setter functions that decide
356the attribute to get or set based on data in the closure.)
357
358<P>
359The setter function is passed the <tt class="class">Noddy</tt> object, the new value,
360and the closure. The new value may be <tt class="constant">NULL</tt>, in which case the
361attribute is being deleted. In our setter, we raise an error if the
362attribute is deleted or if the attribute value is not a string.
363
364<P>
365We create an array of <tt class="ctype">PyGetSetDef</tt> structures:
366
367<P>
368<div class="verbatim"><pre>
369static PyGetSetDef Noddy_getseters[] = {
370 {"first",
371 (getter)Noddy_getfirst, (setter)Noddy_setfirst,
372 "first name",
373 NULL},
374 {"last",
375 (getter)Noddy_getlast, (setter)Noddy_setlast,
376 "last name",
377 NULL},
378 {NULL} /* Sentinel */
379};
380</pre></div>
381
382<P>
383and register it in the <tt class="member">tp_getset</tt> slot:
384
385<P>
386<div class="verbatim"><pre>
387 Noddy_getseters, /* tp_getset */
388</pre></div>
389
390<P>
391to register out attribute getters and setters.
392
393<P>
394The last item in a <tt class="ctype">PyGetSetDef</tt> structure is the closure
395mentioned above. In this case, we aren't using the closure, so we just
396pass <tt class="constant">NULL</tt>.
397
398<P>
399We also remove the member definitions for these attributes:
400
401<P>
402<div class="verbatim"><pre>
403static PyMemberDef Noddy_members[] = {
404 {"number", T_INT, offsetof(Noddy, number), 0,
405 "noddy number"},
406 {NULL} /* Sentinel */
407};
408</pre></div>
409
410<P>
411We also need to update the <tt class="member">tp_init</tt> handler to only allow
412strings<A NAME="tex2html7"
413 HREF="#foot1157"><SUP>2.3</SUP></A> to be passed:
414
415<P>
416<div class="verbatim"><pre>
417static int
418Noddy_init(Noddy *self, PyObject *args, PyObject *kwds)
419{
420 PyObject *first=NULL, *last=NULL, *tmp;
421
422 static char *kwlist[] = {"first", "last", "number", NULL};
423
424 if (! PyArg_ParseTupleAndKeywords(args, kwds, "|SSi", kwlist,
425 &amp;first, &amp;last,
426 &amp;self-&gt;number))
427 return -1;
428
429 if (first) {
430 tmp = self-&gt;first;
431 Py_INCREF(first);
432 self-&gt;first = first;
433 Py_DECREF(tmp);
434 }
435
436 if (last) {
437 tmp = self-&gt;last;
438 Py_INCREF(last);
439 self-&gt;last = last;
440 Py_DECREF(tmp);
441 }
442
443 return 0;
444}
445</pre></div>
446
447<P>
448With these changes, we can assure that the <tt class="member">first</tt> and
449<tt class="member">last</tt> members are never <tt class="constant">NULL</tt> so we can remove checks for <tt class="constant">NULL</tt>
450values in almost all cases. This means that most of the
451<tt class="cfunction">Py_XDECREF()</tt> calls can be converted to <tt class="cfunction">Py_DECREF()</tt>
452calls. The only place we can't change these calls is in the
453deallocator, where there is the possibility that the initialization of
454these members failed in the constructor.
455
456<P>
457We also rename the module initialization function and module name in
458the initialization function, as we did before, and we add an extra
459definition to the <span class="file">setup.py</span> file.
460
461<P>
462<BR><HR><H4>Footnotes</H4>
463<DL>
464<DT><A NAME="foot1157">...
465strings</A><A
466 HREF="node23.html#tex2html7"><SUP>2.3</SUP></A></DT>
467<DD>We now know that the first and last members are strings,
468so perhaps we could be less careful about decrementing their
469reference counts, however, we accept instances of string subclasses.
470Even though deallocating normal strings won't call back into our
471objects, we can't guarantee that deallocating an instance of a string
472subclass won't. call back into out objects.
473
474</DD>
475</DL>
476<DIV CLASS="navigation">
477<div class='online-navigation'>
478<p></p><hr />
479<table align="center" width="100%" cellpadding="0" cellspacing="2">
480<tr>
481<td class='online-navigation'><a rel="prev" title="2.1.1 Adding data and"
482 href="node22.html"><img src='../icons/previous.png'
483 border='0' height='32' alt='Previous Page' width='32' /></A></td>
484<td class='online-navigation'><a rel="parent" title="2.1 The Basics"
485 href="dnt-basics.html"><img src='../icons/up.png'
486 border='0' height='32' alt='Up One Level' width='32' /></A></td>
487<td class='online-navigation'><a rel="next" title="2.1.3 Supporting cyclic garbage"
488 href="node24.html"><img src='../icons/next.png'
489 border='0' height='32' alt='Next Page' width='32' /></A></td>
490<td align="center" width="100%">Extending and Embedding the Python Interpreter</td>
491<td class='online-navigation'><a rel="contents" title="Table of Contents"
492 href="contents.html"><img src='../icons/contents.png'
493 border='0' height='32' alt='Contents' width='32' /></A></td>
494<td class='online-navigation'><img src='../icons/blank.png'
495 border='0' height='32' alt='' width='32' /></td>
496<td class='online-navigation'><img src='../icons/blank.png'
497 border='0' height='32' alt='' width='32' /></td>
498</tr></table>
499<div class='online-navigation'>
500<b class="navlabel">Previous:</b>
501<a class="sectref" rel="prev" href="node22.html">2.1.1 Adding data and</A>
502<b class="navlabel">Up:</b>
503<a class="sectref" rel="parent" href="dnt-basics.html">2.1 The Basics</A>
504<b class="navlabel">Next:</b>
505<a class="sectref" rel="next" href="node24.html">2.1.3 Supporting cyclic garbage</A>
506</div>
507</div>
508<hr />
509<span class="release-info">Release 2.4.2, documentation updated on 28 September 2005.</span>
510</DIV>
511<!--End of Navigation Panel-->
512<ADDRESS>
513See <i><a href="about.html">About this document...</a></i> for information on suggesting changes.
514</ADDRESS>
515</BODY>
516</HTML>