|
1 | | -\chapter{Defining New Object Types \label{newTypes}} |
| 1 | +\chapter{Object Implementation Support \label{newTypes}} |
| 2 | + |
| 3 | + |
| 4 | +This chapter describes the functions, types, and macros used when |
| 5 | +defining new object types. |
2 | 6 |
|
3 | 7 |
|
4 | 8 | \section{Allocating Objects on the Heap |
@@ -388,6 +392,12 @@ \section{Supporting Cyclic Garbarge Collection |
388 | 392 | references to atomic types (such as numbers or strings), do not need |
389 | 393 | to provide any explicit support for garbage collection. |
390 | 394 |
|
| 395 | +An example showing the use of these interfaces can be found in |
| 396 | +``\ulink{Supporting the Cycle |
| 397 | +Collector}{../ext/example-cycle-support.html}'' in |
| 398 | +\citetitle[../ext/ext.html]{Extending and Embedding the Python |
| 399 | +Interpreter}. |
| 400 | + |
391 | 401 | To create a container type, the \member{tp_flags} field of the type |
392 | 402 | object must include the \constant{Py_TPFLAGS_HAVE_GC} and provide an |
393 | 403 | implementation of the \member{tp_traverse} handler. If instances of the |
@@ -504,103 +514,3 @@ \section{Supporting Cyclic Garbarge Collection |
504 | 514 | this method if it detects that this object is involved in a |
505 | 515 | reference cycle. |
506 | 516 | \end{ctypedesc} |
507 | | - |
508 | | - |
509 | | -\subsection{Example Cycle Collector Support |
510 | | - \label{example-cycle-support}} |
511 | | - |
512 | | -This example shows only enough of the implementation of an extension |
513 | | -type to show how the garbage collector support needs to be added. It |
514 | | -shows the definition of the object structure, the |
515 | | -\member{tp_traverse}, \member{tp_clear} and \member{tp_dealloc} |
516 | | -implementations, the type structure, and a constructor --- the module |
517 | | -initialization needed to export the constructor to Python is not shown |
518 | | -as there are no special considerations there for the collector. To |
519 | | -make this interesting, assume that the module exposes ways for the |
520 | | -\member{container} field of the object to be modified. Note that |
521 | | -since no checks are made on the type of the object used to initialize |
522 | | -\member{container}, we have to assume that it may be a container. |
523 | | - |
524 | | -\begin{verbatim} |
525 | | -#include "Python.h" |
526 | | -
|
527 | | -typedef struct { |
528 | | - PyObject_HEAD |
529 | | - PyObject *container; |
530 | | -} MyObject; |
531 | | -
|
532 | | -static int |
533 | | -my_traverse(MyObject *self, visitproc visit, void *arg) |
534 | | -{ |
535 | | - if (self->container != NULL) |
536 | | - return visit(self->container, arg); |
537 | | - else |
538 | | - return 0; |
539 | | -} |
540 | | -
|
541 | | -static int |
542 | | -my_clear(MyObject *self) |
543 | | -{ |
544 | | - Py_XDECREF(self->container); |
545 | | - self->container = NULL; |
546 | | -
|
547 | | - return 0; |
548 | | -} |
549 | | -
|
550 | | -static void |
551 | | -my_dealloc(MyObject *self) |
552 | | -{ |
553 | | - PyObject_GC_UnTrack((PyObject *) self); |
554 | | - Py_XDECREF(self->container); |
555 | | - PyObject_GC_Del(self); |
556 | | -} |
557 | | -\end{verbatim} |
558 | | - |
559 | | -\begin{verbatim} |
560 | | -statichere PyTypeObject |
561 | | -MyObject_Type = { |
562 | | - PyObject_HEAD_INIT(NULL) |
563 | | - 0, |
564 | | - "MyObject", |
565 | | - sizeof(MyObject), |
566 | | - 0, |
567 | | - (destructor)my_dealloc, /* tp_dealloc */ |
568 | | - 0, /* tp_print */ |
569 | | - 0, /* tp_getattr */ |
570 | | - 0, /* tp_setattr */ |
571 | | - 0, /* tp_compare */ |
572 | | - 0, /* tp_repr */ |
573 | | - 0, /* tp_as_number */ |
574 | | - 0, /* tp_as_sequence */ |
575 | | - 0, /* tp_as_mapping */ |
576 | | - 0, /* tp_hash */ |
577 | | - 0, /* tp_call */ |
578 | | - 0, /* tp_str */ |
579 | | - 0, /* tp_getattro */ |
580 | | - 0, /* tp_setattro */ |
581 | | - 0, /* tp_as_buffer */ |
582 | | - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, |
583 | | - 0, /* tp_doc */ |
584 | | - (traverseproc)my_traverse, /* tp_traverse */ |
585 | | - (inquiry)my_clear, /* tp_clear */ |
586 | | - 0, /* tp_richcompare */ |
587 | | - 0, /* tp_weaklistoffset */ |
588 | | -}; |
589 | | -
|
590 | | -/* This constructor should be made accessible from Python. */ |
591 | | -static PyObject * |
592 | | -new_object(PyObject *unused, PyObject *args) |
593 | | -{ |
594 | | - PyObject *container = NULL; |
595 | | - MyObject *result = NULL; |
596 | | -
|
597 | | - if (PyArg_ParseTuple(args, "|O:new_object", &container)) { |
598 | | - result = PyObject_GC_New(MyObject, &MyObject_Type); |
599 | | - if (result != NULL) { |
600 | | - result->container = container; |
601 | | - PyObject_GC_Track(result); |
602 | | - } |
603 | | - } |
604 | | - return (PyObject *) result; |
605 | | -} |
606 | | -\end{verbatim} |
0 commit comments