3. Defining Extension Types: Assorted Topics
********************************************

この節ではさまざまな実装可能なタイプメソッドと、それらが何をするもので
あるかについて、ざっと説明します。

以下は "PyTypeObject" の定義です。デバッグビルドでしか使われないいくつ
かのメンバは省いてあります:

   typedef struct _typeobject {
       PyObject_VAR_HEAD
       const char *tp_name; /* For printing, in format "<module>.<name>" */
       Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */

       /* Methods to implement standard operations */

       destructor tp_dealloc;
       printfunc tp_print;
       getattrfunc tp_getattr;
       setattrfunc tp_setattr;
       PyAsyncMethods *tp_as_async; /* formerly known as tp_compare (Python 2)
                                       or tp_reserved (Python 3) */
       reprfunc tp_repr;

       /* Method suites for standard classes */

       PyNumberMethods *tp_as_number;
       PySequenceMethods *tp_as_sequence;
       PyMappingMethods *tp_as_mapping;

       /* More standard operations (here for binary compatibility) */

       hashfunc tp_hash;
       ternaryfunc tp_call;
       reprfunc tp_str;
       getattrofunc tp_getattro;
       setattrofunc tp_setattro;

       /* Functions to access object as input/output buffer */
       PyBufferProcs *tp_as_buffer;

       /* Flags to define presence of optional/expanded features */
       unsigned long tp_flags;

       const char *tp_doc; /* Documentation string */

       /* call function for all accessible objects */
       traverseproc tp_traverse;

       /* delete references to contained objects */
       inquiry tp_clear;

       /* rich comparisons */
       richcmpfunc tp_richcompare;

       /* weak reference enabler */
       Py_ssize_t tp_weaklistoffset;

       /* Iterators */
       getiterfunc tp_iter;
       iternextfunc tp_iternext;

       /* Attribute descriptor and subclassing stuff */
       struct PyMethodDef *tp_methods;
       struct PyMemberDef *tp_members;
       struct PyGetSetDef *tp_getset;
       struct _typeobject *tp_base;
       PyObject *tp_dict;
       descrgetfunc tp_descr_get;
       descrsetfunc tp_descr_set;
       Py_ssize_t tp_dictoffset;
       initproc tp_init;
       allocfunc tp_alloc;
       newfunc tp_new;
       freefunc tp_free; /* Low-level free-memory routine */
       inquiry tp_is_gc; /* For PyObject_IS_GC */
       PyObject *tp_bases;
       PyObject *tp_mro; /* method resolution order */
       PyObject *tp_cache;
       PyObject *tp_subclasses;
       PyObject *tp_weaklist;
       destructor tp_del;

       /* Type attribute cache version tag. Added in version 2.6 */
       unsigned int tp_version_tag;

       destructor tp_finalize;

   } PyTypeObject;

*たくさんの* メソッドがありますね。でもそんなに心配する必要はありませ
ん。定義したい型があるなら、実装するのはこのうちのごくわずかですむこと
がほとんどです。

すでに予想されているでしょうが、この構造体について入念に見ていき、様々
なハンドラについてより詳しい情報を提供します。 しかしこれらのメンバが
構造体中で定義されている順番は無視します。というのは、これらのメンバの
現れる順序は歴史的な遺産によるものだからです。 多くの場合いちばん簡単
なのは、必要とするメンバがすべて含まれている例をとってきて、新しく作る
型に合わせて値を変更することです。

   const char *tp_name; /* For printing */

これは型の名前です。前の章で説明したように、これは色々な場面で現れ、ほ
とんどは診断目的で使われるものです。 それなので、そのような場面で役に
立つであろう名前を選んでください!

   Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */

これらのフィールドは、この型のオブジェクトが新しく作成されるときにどれ
だけのメモリを割り当てればよいのかをランタイムに指示します。Python に
は可変長の構造体 (文字列やタプルなどを想像してください) に対する組み込
みのサポートがある程度あり、ここで "tp_itemsize" メンバが使われます。
これらについてはあとでふれます。

   const char *tp_doc;

ここには Python スクリプトリファレンス "obj.__doc__" が doc string を
返すときの文字列 (あるいはそのアドレス) を入れます。

では次に、型の基本的なメソッドに進みます。ほとんどの拡張の型がこのメソ
ッドを実装します。


3.1. ファイナライズとメモリ解放
===============================

   destructor tp_dealloc;

型のインスタンスの参照カウントがゼロになり、Python インタプリタがそれ
を潰して再利用したくなると、この関数が呼ばれます。解放すべきメモリをそ
の型が保持していたり、それ以外にも実行すべき後処理がある場合は、それら
をここに入れられます。オブジェクトそれ自体もここで解放される必要があり
ます。この関数の例は、以下のようなものです:

   static void
   newdatatype_dealloc(newdatatypeobject *obj)
   {
       free(obj->obj_UnderlyingDatatypePtr);
       Py_TYPE(obj)->tp_free(obj);
   }

メモリ解放関数でひとつ重要なのは、処理待ちの例外にいっさい手をつけない
ことです。なぜなら、解放用の関数は Python インタプリタがスタックを元の
状態に戻すときに呼ばれることが多いからです。そして (通常の関数からの復
帰でなく) 例外のためにスタックが巻き戻されるときは、すでに発生している
例外からメモリ解放関数を守るものはありません。解放用の関数がおこなう動
作が追加の Python のコードを実行してしまうと、それらは例外が発生してい
ることを検知するかもしれません。これはインタプリタが誤解させるエラーを
発生させることにつながります。これを防ぐ正しい方法は、安全でない操作を
実行する前に処理待ちの例外を保存しておき、終わったらそれを元に戻すこと
です。これは "PyErr_Fetch()" および "PyErr_Restore()" 関数を使うことに
よって可能になります:

   static void
   my_dealloc(PyObject *obj)
   {
       MyObject *self = (MyObject *) obj;
       PyObject *cbresult;

       if (self->my_callback != NULL) {
           PyObject *err_type, *err_value, *err_traceback;

           /* This saves the current exception state */
           PyErr_Fetch(&err_type, &err_value, &err_traceback);

           cbresult = PyObject_CallObject(self->my_callback, NULL);
           if (cbresult == NULL)
               PyErr_WriteUnraisable(self->my_callback);
           else
               Py_DECREF(cbresult);

           /* This restores the saved exception state */
           PyErr_Restore(err_type, err_value, err_traceback);

           Py_DECREF(self->my_callback);
       }
       Py_TYPE(obj)->tp_free((PyObject*)self);
   }

注釈:

  メモリ解放関数の中で安全に行えることにはいくつか制限があります。 1つ
  目は、その型が ("tp_traverse" および "tp_clear" を使って) ガベージコ
  レクションをサポートしている場合、 "tp_dealloc" が呼び出されるまでに
  、消去されファイナライズされてしまうオブジェクトのメンバーが有り得る
  ことです。 2つ目は、 "tp_dealloc" の中ではオブジェクトは不安定な状態
  にあることです: つまり参照カウントが0であるということです。 (上の例
  にあるような) 複雑なオブジェクトや API の呼び出しでは、 "tp_dealloc"
  を再度呼び出し、二重解放からクラッシュすることになるかもしれません。
  Python 3.4 からは、複雑なファイナライズのコードは "tp_dealloc" に置
  かず、代わりに新しく導入された "tp_finalize" という型メソッドを使う
  ことが推奨されています。

  参考: **PEP 442** で新しいファイナライズの仕組みが説明されています。


3.2. オブジェクト表現
=====================

Python では、オブジェクトの文字列表現を生成するのに 2つのやり方があり
ます: "repr()" 関数を使う方法と、 "str()"  関数を使う方法です。
("print()" 関数は単に "str()" を呼び出します。) これらのハンドラはどち
らも省略できます。

   reprfunc tp_repr;
   reprfunc tp_str;

"tp_repr" ハンドラは呼び出されたインスタンスの文字列表現を格納した文字
列オブジェクトを返す必要があります。簡単な例は以下のようなものです:

   static PyObject *
   newdatatype_repr(newdatatypeobject * obj)
   {
       return PyUnicode_FromFormat("Repr-ified_newdatatype{{size:%d}}",
                                   obj->obj_UnderlyingDatatypePtr->size);
   }

"tp_repr" ハンドラが指定されていなければ、インタプリタはその型の
"tp_name" とそのオブジェクトの一意な識別値をもちいて文字列表現を作成し
ます。

"tp_str" ハンドラと "str()" の関係は、上の "tp_repr" ハンドラと
"repr()" の関係に相当します。つまり、これは Python のコードがオブジェ
クトのインスタンスに対して "str()" を呼び出したときに呼ばれます。この
関数の実装は "tp_repr" ハンドラのそれと非常に似ていますが、得られる文
字列表現は人間が読むことを意図されています。 "tp_str" が指定されていな
い場合、かわりに "tp_repr" ハンドラが使われます。

以下は簡単な例です:

   static PyObject *
   newdatatype_str(newdatatypeobject * obj)
   {
       return PyUnicode_FromFormat("Stringified_newdatatype{{size:%d}}",
                                   obj->obj_UnderlyingDatatypePtr->size);
   }


3.3. 属性を管理する
===================

属性をもつどのオブジェクトに対しても、その型は、それらオブジェクトの属
性をどのように解決するか制御する関数を提供する必要があります。必要な関
数としては、属性を (それが定義されていれば) 取り出すものと、もうひとつ
は属性に (それが許可されていれば) 値を設定するものです。属性を削除する
のは特殊なケースで、この場合は新しい値としてハンドラに *NULL* が渡され
ます。

Python は 2つの属性ハンドラの組をサポートしています。属性をもつ型はど
ちらか一組を実装するだけでよく、それらの違いは一方の組が属性の名前を
"char*" として受け取るのに対してもう一方の組は属性の名前を "PyObject*"
として受け取る、というものです。それぞれの型はその実装にとって都合がよ
い方を使えます。

   getattrfunc  tp_getattr;        /* char * version */
   setattrfunc  tp_setattr;
   /* ... */
   getattrofunc tp_getattro;       /* PyObject * version */
   setattrofunc tp_setattro;

オブジェクトの属性へのアクセスがつねに (すぐあとで説明する) 単純な操作
だけならば、 "PyObject*" を使って属性を管理する関数として、総称的
(generic) な実装を使えます。特定の型に特化した属性ハンドラの必要性は
Python 2.2 からほとんど完全になくなりました。しかし、多くの例はまだ、
この新しく使えるようになった総称的なメカニズムを使うよう更新されてはい
ません。


3.3.1. 総称的な属性を管理する
-----------------------------

ほとんどの型は *単純な* 属性を使うだけです。では、どのような属性が単純
だといえるのでしょうか? それが満たすべき条件はごくわずかです:

1. "PyType_Ready()" が呼ばれたとき、すでに属性の名前がわかっていること
   。

2. 属性を参照したり設定したりするときに、特別な記録のための処理が必要
   でなく、また参照したり設定した値に対してどんな操作も実行する必要が
   ないこと。

これらの条件は、属性の値や、値が計算されるタイミング、または格納された
データがどの程度妥当なものであるかといったことになんら制約を課すもので
はないことに注意してください。

"PyType_Ready()" が呼ばれると、これはそのタイプオブジェクトに参照され
ている 3つのテーブルを使って、そのタイプオブジェクトの辞書中にデスクリ
プタ(*descriptor*) を作成します。各デスクリプタは、インスタンスオブジ
ェクトの属性に対するアクセスを制御します。それぞれのテーブルはなくても
かまいません。もしこれら 3つがすべて *NULL* だと、その型のインスタンス
はその基底型から継承した属性だけを持つことになります。また、
"tp_getattro" および "tp_setattro" が *NULL* のままだった場合も、基底
型にこれらの属性の操作がまかせられます。

テーブルはタイプオブジェクト中の 3つのメンバとして宣言されています:

   struct PyMethodDef *tp_methods;
   struct PyMemberDef *tp_members;
   struct PyGetSetDef *tp_getset;

"tp_methods" が *NULL* でない場合、これは "PyMethodDef" 構造体への配列
を指している必要があります。テーブル中の各エントリは、つぎのような構造
体のインスタンスです:

   typedef struct PyMethodDef {
       const char  *ml_name;       /* method name */
       PyCFunction  ml_meth;       /* implementation function */
       int          ml_flags;      /* flags */
       const char  *ml_doc;        /* docstring */
   } PyMethodDef;

その型が提供する各メソッドについてひとつのエントリを定義する必要があり
ます。基底型から継承してきたメソッドについてはエントリは必要ありません
。これの最後には、配列の終わりを示すための見張り番 (sentinel) として追
加のエントリがひとつ必要です。この場合、 "ml_name" メンバが sentinel
として使われ、その値は *NULL* でなければなりません。

2番目のテーブルは、インスタンス中に格納されるデータと直接対応づけられ
た属性を定義するのに使います。いくつもの C の原始的な型がサポートされ
ており、アクセスを読み出し専用にも読み書き可能にもできます。このテーブ
ルで使われる構造体は次のように定義されています:

   typedef struct PyMemberDef {
       char *name;
       int   type;
       int   offset;
       int   flags;
       char *doc;
   } PyMemberDef;

このテーブルの各エントリに対してデスクリプタ(*descriptor*)が作成され、
値をインスタンスの構造体から抽出しうる型に対してそれらが追加されます。
"type" メンバは "structmember.h" ヘッダで定義された型のコードをひとつ
含んでいる必要があります。この値は Python における値と C における値を
どのように変換しあうかを定めるものです。 "flags" メンバはこの属性がど
のようにアクセスされるかを制御するフラグを格納するのに使われます。

以下のフラグ用定数は "structmember.h" で定義されており、これらはビット
ごとの OR を取って組み合わせられます。

+-----------------------------+------------------------------------------------+
| 定数                        | 意味                                           |
|=============================|================================================|
| "READONLY"                  | 絶対に変更できない。                           |
+-----------------------------+------------------------------------------------+
| "READ_RESTRICTED"           | 制限モード (restricted mode) では参照できない  |
|                             | 。                                             |
+-----------------------------+------------------------------------------------+
| "WRITE_RESTRICTED"          | 制限モード (restricted mode) では変更できない  |
|                             | 。                                             |
+-----------------------------+------------------------------------------------+
| "RESTRICTED"                | 制限モード (restricted mode) では参照も変更も  |
|                             | できない。                                     |
+-----------------------------+------------------------------------------------+

"tp_members" を使ったひとつの面白い利用法は、実行時に使われるデスクリ
プタを作成しておき、単にテーブル中にテキストを置いておくことによって、
この方法で定義されたすべての属性に doc string を関連付けられるようにす
ることです。アプリケーションはこのイントロスペクション用 API を使って
、クラスオブジェクトからデスクリプタを取り出し、その "__doc__" 属性を
使って doc string を得られます。

"tp_methods" テーブルと同じように、ここでも "name" メンバの値を *NULL*
にした見張り用エントリが必要です。


3.3.2. 特定の型に特化した属性の管理
-----------------------------------

話を単純にするため、ここでは "char*" を使ったバージョンのみを示します
。name パラメータの型はインターフェイスとして "char*" を使うか
"PyObject*" を使うかの違いしかありません。この例では、上の総称的な例と
同じことを効率的にやりますが、 Python 2.2 で追加された総称的な型のサポ
ートを使わずにやります。これはハンドラの関数がどのようにして呼ばれるの
かを説明します。これで、たとえその機能を拡張する必要があるとき、何をど
うすればいいかわかるでしょう。

"tp_getattr" ハンドラはオブジェクトが属性への参照を要求するときに呼ば
れます。これは、そのクラスの "__getattr__()" メソッドが呼ばれるであろ
う状況と同じ状況下で呼び出されます。

以下に例を示します。:

   static PyObject *
   newdatatype_getattr(newdatatypeobject *obj, char *name)
   {
       if (strcmp(name, "data") == 0)
       {
           return PyLong_FromLong(obj->data);
       }

       PyErr_Format(PyExc_AttributeError,
                    "'%.50s' object has no attribute '%.400s'",
                    tp->tp_name, name);
       return NULL;
   }

"tp_setattr" ハンドラは、クラスのインスタンスの "__setattr__()" または
"__delattr__()" メソッドが呼ばれるであろう状況で呼び出されます。ある属
性が削除されるとき、3番目のパラメータは *NULL* になります。以下の例は
たんに例外を発生させるものですが、もし本当にこれと同じことをしたいなら
、 "tp_setattr" ハンドラを *NULL* に設定すべきです。

   static int
   newdatatype_setattr(newdatatypeobject *obj, char *name, PyObject *v)
   {
       PyErr_Format(PyExc_RuntimeError, "Read-only attribute: %s", name);
       return -1;
   }


3.4. オブジェクトの比較
=======================

   richcmpfunc tp_richcompare;

"tp_richcompare" ハンドラは比較処理が要求されたときに呼び出されます。
"__lt__()" のような 拡張比較メソッド に類似しており、
"PyObject_RichCompare()" と "PyObject_RichCompareBool()" からも呼び出
されます。

この関数は 2 つの Python オブジェクトと演算子を引数に取り、演算子は
"Py_EQ", "Py_NE", "Py_LE", "Py_GT", "Py_LT", "Py_GT" のどれか 1 つです
。関数は指定された演算子に従って 2 つのオブジェクトを比較し、比較に成
功した場合の "Py_True" および "Py_False" か、比較処理が実装されておら
ず、もう一方のオブジェクトの比較処理を試行することを示す
"Py_NotImplemented" か、例外が設定された場合の *NULL* のいづれかを返し
ます。

これは内部ポインタのサイズが等しければ等しいと見なすデータ型のサンプル
実装です:

   static PyObject *
   newdatatype_richcmp(PyObject *obj1, PyObject *obj2, int op)
   {
       PyObject *result;
       int c, size1, size2;

       /* code to make sure that both arguments are of type
          newdatatype omitted */

       size1 = obj1->obj_UnderlyingDatatypePtr->size;
       size2 = obj2->obj_UnderlyingDatatypePtr->size;

       switch (op) {
       case Py_LT: c = size1 <  size2; break;
       case Py_LE: c = size1 <= size2; break;
       case Py_EQ: c = size1 == size2; break;
       case Py_NE: c = size1 != size2; break;
       case Py_GT: c = size1 >  size2; break;
       case Py_GE: c = size1 >= size2; break;
       }
       result = c ? Py_True : Py_False;
       Py_INCREF(result);
       return result;
    }


3.5. 抽象的なプロトコルのサポート
=================================

Python はいくつもの *抽象的な* “プロトコル”をサポートしています。これ
らを使用する特定のインターフェイスについては 抽象オブジェクトレイヤ
(abstract objects layer) で解説されています。

これら多数の抽象的なインターフェイスは、Python の実装が開発される初期
の段階で定義されていました。とりわけ数値や辞書、そしてシーケンスなどの
プロトコルは最初から Python の一部だったのです。それ以外のプロトコルは
その後追加されました。型の実装にあるいくつかのハンドラルーチンに依存す
るようなプロトコルのために、古いプロトコルはハンドラの入ったオプション
のブロックとして定義し、型オブジェクトから参照するようになりました。タ
イプオブジェクトの主部に追加のスロットをもつ新しいプロトコルについては
、フラグ用のビットを立てることでそれらのスロットが存在しており、インタ
プリタがチェックすべきであることを指示できます。(このフラグ用のビット
は、そのスロットの値が非 *NULL* であることを示しているわけではありませ
ん。フラグはスロットの存在を示すのに使えますが、そのスロットはまだ埋ま
っていないかもしれないのです。)

   PyNumberMethods   *tp_as_number;
   PySequenceMethods *tp_as_sequence;
   PyMappingMethods  *tp_as_mapping;

お使いのオブジェクトを数値やシーケンス、あるいは辞書のようにふるまうよ
うにしたいならば、それぞれに C の "PyNumberMethods" 構造体、
"PySequenceMethods" 構造体、または "PyMappingMethods" 構造体のアドレス
を入れます。これらに適切な値を入れても入れなくてもかまいません。これら
を使った例は Python の配布ソースにある "Objects" でみつけることができ
るでしょう。

   hashfunc tp_hash;

この関数は、もし使うことにしたならば、データ型のインスタンスのハッシュ
番号を返すようにします。次のは単純な例です:

   static Py_hash_t
   newdatatype_hash(newdatatypeobject *obj)
   {
       Py_hash_t result;
       result = obj->some_size + 32767 * obj->some_number;
       if (result == -1)
          result = -2;
       return result;
   }

"Py_hash_t" is a signed integer type with a platform-varying width.
Returning "-1" from "tp_hash" indicates an error, which is why you
should be careful to avoid returning it when hash computation is
successful, as seen above.

   ternaryfunc tp_call;

この関数は、その型のインスタンスが「関数として呼び出される」ときに呼ば
れます。たとえばもし "obj1" にそのインスタンスが入っていて、Python ス
クリプトで "obj1('hello')" を実行したとすると、 "tp_call" ハンドラが呼
ばれます。

この関数は 3つの引数をとります:

1. *self* は呼び出しの対象となるデータ型のインスタンスです。 たとえば
   呼び出しが "obj1('hello')" の場合、*self* は "obj1" になります。

2. *args* は呼び出しの引数を格納しているタプルです。ここから引数を取り
   出すには "PyArg_ParseTuple()" を使います。

3. *kwds* はキーワード引数のための辞書です。これが *NULL* でなく、キー
   ワード引数をサポートしている場合は、
   "PyArg_ParseTupleAndKeywords()" をつかって引数を取り出せます。キー
   ワード引数をサポートしていないのにこれが *NULL* でない場合は、キー
   ワード引数はサポートしていない旨のメッセージとともに "TypeError" を
   発生させてください。

以下は "tp_call" の簡易な実装です:

   static PyObject *
   newdatatype_call(newdatatypeobject *self, PyObject *args, PyObject *kwds)
   {
       PyObject *result;
       char *arg1;
       char *arg2;
       char *arg3;

       if (!PyArg_ParseTuple(args, "sss:call", &arg1, &arg2, &arg3)) {
           return NULL;
       }
       result = PyUnicode_FromFormat(
           "Returning -- value: [%d] arg1: [%s] arg2: [%s] arg3: [%s]\n",
           obj->obj_UnderlyingDatatypePtr->size,
           arg1, arg2, arg3);
       return result;
   }

   /* Iterators */
   getiterfunc tp_iter;
   iternextfunc tp_iternext;

These functions provide support for the iterator protocol.  Both
handlers take exactly one parameter, the instance for which they are
being called, and return a new reference.  In the case of an error,
they should set an exception and return *NULL*.  "tp_iter" corresponds
to the Python "__iter__()" method, while "tp_iternext" corresponds to
the Python "__next__()" method.

Any *iterable* object must implement the "tp_iter" handler, which must
return an *iterator* object.  Here the same guidelines apply as for
Python classes:

* For collections (such as lists and tuples) which can support
  multiple independent iterators, a new iterator should be created and
  returned by each call to "tp_iter".

* Objects which can only be iterated over once (usually due to side
  effects of iteration, such as file objects) can implement "tp_iter"
  by returning a new reference to themselves -- and should also
  therefore implement the "tp_iternext"  handler.

Any *iterator* object should implement both "tp_iter" and
"tp_iternext".  An iterator's "tp_iter" handler should return a new
reference to the iterator.  Its "tp_iternext" handler should return a
new reference to the next object in the iteration, if there is one. If
the iteration has reached the end, "tp_iternext" may return *NULL*
without setting an exception, or it may set "StopIteration" *in
addition* to returning *NULL*; avoiding the exception can yield
slightly better performance.  If an actual error occurs, "tp_iternext"
should always set an exception and return *NULL*.


3.6. 弱参照(Weak Reference)のサポート
=====================================

One of the goals of Python's weak reference implementation is to allow
any type to participate in the weak reference mechanism without
incurring the overhead on performance-critical objects (such as
numbers).

参考: Documentation for the "weakref" module.

For an object to be weakly referencable, the extension type must do
two things:

1. Include a "PyObject*" field in the C object structure dedicated to
   the weak reference mechanism.  The object's constructor should
   leave it *NULL* (which is automatic when using the default
   "tp_alloc").

2. Set the "tp_weaklistoffset" type member to the offset of the
   aforementioned field in the C object structure, so that the
   interpreter knows how to access and modify that field.

Concretely, here is how a trivial object structure would be augmented
with the required field:

   typedef struct {
       PyObject_HEAD
       PyObject *weakreflist;  /* List of weak references */
   } TrivialObject;

And the corresponding member in the statically-declared type object:

   static PyTypeObject TrivialType = {
       PyVarObject_HEAD_INIT(NULL, 0)
       /* ... other members omitted for brevity ... */
       .tp_weaklistoffset = offsetof(TrivialObject, weakreflist),
   };

The only further addition is that "tp_dealloc" needs to clear any weak
references (by calling "PyObject_ClearWeakRefs()") if the field is
non-*NULL*:

   static void
   Trivial_dealloc(TrivialObject *self)
   {
       /* Clear weakrefs first before calling any destructors */
       if (self->weakreflist != NULL)
           PyObject_ClearWeakRefs((PyObject *) self);
       /* ... remainder of destruction code omitted for brevity ... */
       Py_TYPE(self)->tp_free((PyObject *) self);
   }


3.7. その他いろいろ
===================

In order to learn how to implement any specific method for your new
data type, get the *CPython* source code.  Go to the "Objects"
directory, then search the C source files for "tp_" plus the function
you want (for example, "tp_richcompare").  You will find examples of
the function you want to implement.

When you need to verify that an object is a concrete instance of the
type you are implementing, use the "PyObject_TypeCheck()" function.  A
sample of its use might be something like the following:

   if (!PyObject_TypeCheck(some_object, &MyType)) {
       PyErr_SetString(PyExc_TypeError, "arg #1 not a mything");
       return NULL;
   }

参考:

  Download CPython source releases.
     https://www.python.org/downloads/source/

  The CPython project on GitHub, where the CPython source code is
  developed.
     https://github.com/python/cpython
