共通のオブジェクト構造体 (common object structure)

Python では、オブジェクト型を定義する上で数多くの構造体が使われます。この節では三つの構造体とその利用方法について説明します。

全ての Python オブジェクトは、オブジェクトのメモリ内表現の先頭部分にある少数のフィールドを完全に共有しています。 このフィールドは PyObject 型および PyVarObject 型で表現されます。 これらの型もまた、他の全ての Python オブジェクトの定義で直接または間接的に使われているマクロを使って定義されています。

PyObject

全てのオブジェクト型はこの型を拡張したものです。 この型には、あるオブジェクトを指すポインタをオブジェクトとして Python から扱うのに必要な情報が入っています。 通常の "リリース" ビルドでは、この構造体にはオブジェクトの参照カウントとオブジェクトに対応する型オブジェクトだけが入っています。 実際には PyObject であることは宣言されていませんが、全ての Python オブジェクトへのポインタは PyObject* へキャストできます。 メンバにアクセスするには Py_REFCNT マクロと Py_TYPE マクロを使わなければなりません。

PyVarObject

PyObject を拡張して、 ob_size フィールドを追加したものです。 この構造体は、 長さ (length) の概念を持つオブジェクトだけに対して使います。 この型が Python/C API で使われることはほとんどありません。 メンバにアクセスするには Py_REFCNT マクロ、 Py_TYPE マクロ、 Py_SIZE マクロを使わなければなりません。

PyObject_HEAD

可変な長さを持たないオブジェクトを表現する新しい型を宣言するときに使うマクロです。 PyObject_HEAD マクロは次のように展開されます:

PyObject ob_base;

上にある PyObject のドキュメントを参照してください。

PyObject_VAR_HEAD

インスタンスごとに異なる長さを持つオブジェクトを表現する新しい型を宣言するときに使うマクロです。 PyObject_VAR_HEAD マクロは次のように展開されます:

PyVarObject ob_base;

上にある PyVarObject のドキュメントを参照してください。

Py_TYPE(o)

Python オブジェクトの ob_type メンバにアクセスするのに使うマクロです。 これは次のように展開されます:

(((PyObject*)(o))->ob_type)
Py_REFCNT(o)

Python オブジェクトの ob_refcnt メンバにアクセスするのに使うマクロです。 これは次のように展開されます:

(((PyObject*)(o))->ob_refcnt)
Py_SIZE(o)

Python オブジェクトの ob_size メンバにアクセスするのに使うマクロです。 これは次のように展開されます:

(((PyVarObject*)(o))->ob_size)
PyObject_HEAD_INIT(type)

新しい PyObject 型のための初期値に展開するマクロです。このマクロは次のように展開されます。

_PyObject_EXTRA_INIT
1, type,
PyVarObject_HEAD_INIT(type, size)

新しい、 ob_size フィールドを含む PyVarObject 型のための初期値に展開するマクロです。このマクロは次のように展開されます。

_PyObject_EXTRA_INIT
1, type, size,
PyCFunction

ほとんどの Python の呼び出し可能オブジェクトを C で実装する際に用いられている関数の型です。この型の関数は 2 つの PyObject* 型のパラメータを取り、 PyObject* 型の値を返します。戻り値を NULL にする場合、例外をセットしておかなければなりません。 NULL でない値を返す場合、戻り値は Python に関数の戻り値として公開される値として解釈されます。この型の関数は新たな参照を返さなければなりません。

PyCFunctionWithKeywords

キーワード引数をとるPythonの呼び出し可能オブジェクトを C で実装する際に用いられている関数の型です: この型の関数は 3 つの PyObject* 型のパラメータをとり、 PyObject* 型の値を返します。戻り値の意味については、上記の PyCFunction を参照して下さい。

PyMethodDef

拡張型のメソッドを記述する際に用いる構造体です。この構造体には 4 つのフィールドがあります:

フィールド C の型 意味
ml_name char * メソッド名
ml_meth PyCFunction C 実装へのポインタ
ml_flags int 呼び出しをどのように行うかを示すフラグビット
ml_doc char * docstring の内容を指すポインタ

ml_meth は C の関数ポインタです。関数は別の型で定義されていてもかまいませんが、常に PyObject* を返します。関数が PyFunction でない場合、メソッドテーブル内でキャストを行うようコンパイラが要求することになるでしょう。 PyCFunction では最初のパラメタが PyObject* 型であると定義していますが、固有の C 型を self オブジェクトに使う実装はよく行われています。

ml_flags フィールドはビットフィールドで、以下のフラグが入ります。 個々のフラグは呼び出し規約 (calling convention) や束縛規約 (binding convention) を表します。 呼び出し規約フラグでは、 METH_VARARGS および METH_KEYWORDS だけが組み合わせられます。 呼び出し規約フラグは束縛規約フラグと組み合わせられます。

METH_VARARGS

PyCFunction 型のメソッドで典型的に使われる呼び出し規約です。関数は PyObject* 型の引数値を二つ要求します。最初の引数はメソッドの self オブジェクトです; モジュール関数の場合、これはモジュールオブジェクトです。第二のパラメタ (よく args と呼ばれます) は、全ての引数を表現するタプルオブジェクトです。パラメタは通常、 PyArg_ParseTuple()PyArg_UnpackTuple() で処理されます。

METH_KEYWORDS

このフラグを持つメソッドは PyCFunctionWithKeywords 型でなければなりません。 この関数は 3 つのパラメータを要求します: selfargs 、およびキーワード引数全てからなる辞書です。 このフラグは METH_VARARGS と組み合わせて用いられなければならず、パラメタは通常 PyArg_ParseTupleAndKeywords() で処理されます。

METH_NOARGS

引数のないメソッドは、 METH_NOARGS フラグをつけた場合、必要な引数が指定されているかをチェックしなくなります。こうしたメソッドは PyCFunction 型でなくてはなりません。第一のパラメタは self になり、モジュールかオブジェクトインスタンスへの参照を保持することになります。いずれにせよ、第二のパラメタは NULL になります。

METH_O

単一のオブジェクト引数だけをとるメソッドは、 PyArg_ParseTuple() を引数 "O" にして呼び出す代わりに、 METH_O フラグつきで指定できます。メソッドは PyCFunction 型で、 self パラメタと単一の引数を表現する PyObject* パラメタを伴います。

以下の二つの定数は、呼び出し規約を示すものではなく、クラスのメソッドとして使う際の束縛方式を示すものです。モジュールに対して定義された関数で用いてはなりません。メソッドに対しては、最大で一つしかこのフラグをセットできません。

METH_CLASS

メソッドの最初の引数には、型のインスタンスではなく型オブジェクトが渡されます。このフラグは組み込み関数 classmethod() を使って生成するのと同じ クラスメソッド (class method) を生成するために使われます。

METH_STATIC

メソッドの最初の引数には、型のインスタンスではなく NULL が渡されます。このフラグは、 staticmethod() を使って生成するのと同じ 静的メソッド (static method) を生成するために使われます。

もう一つの定数は、あるメソッドを同名の別のメソッド定義と置き換えるかどうかを制御します。

METH_COEXIST

メソッドを既存の定義を置き換える形でロードします。 METH_COEXIST を指定しなければ、デフォルトの設定にしたがって、定義が重複しないようスキップします。スロットラッパはメソッドテーブルよりも前にロードされるので、例えば sq_contains スロットはラップしているメソッド __contains__() を生成し、同名の PyCFunction のロードを阻止します。このフラグを定義すると、 PyCFunction はラッパオブジェクトを置き換える形でロードされ、スロットと連立します。 PyCFunctions の呼び出しはラッパオブジェクトの呼び出しよりも最適化されているので、こうした仕様が便利になります。

PyMemberDef

type の C 構造体のメンバとして格納されている、ある型の属性を表す構造体です。この構造体のフィールドは以下のとおりです:

フィールド C の型 意味
name char * メンバ名
type int C 構造体の中のメンバの型
offset Py_ssize_t そのメンバの type object 構造体中の場所の offset バイト数
flags int フィールドが読み出し専用か書込み可能なのかを示すビットフラグ
doc char * docstring の内容を指すポインタ

type はたくさんのCの型を意味する T_ マクロのうちの1つです。メンバが Python からアクセスされるとき、そのメンバは対応する Python の型に変換されます。

マクロ名 C の型
T_SHORT short
T_INT int
T_LONG long
T_FLOAT 浮動小数点数
T_DOUBLE double
T_STRING char *
T_OBJECT PyObject *
T_OBJECT_EX PyObject *
T_CHAR char
T_BYTE char
T_UBYTE unsigned char
T_UINT unsigned int
T_USHORT unsigned short
T_ULONG unsigned long
T_BOOL char
T_LONGLONG long long
T_ULONGLONG unsigned long long
T_PYSSIZET Py_ssize_t

T_OBJECTT_OBJECT_EX が異なっているのは、 T_OBJECT はメンバが NULL だったときに None を返すのに対し、 T_OBJECT_EXAttributeError を送出する点です。 T_OBJECT_EXT_OBJECT より属性に対する del 文を正しくあつかうので、できれば T_OBJECT ではなく T_OBJECT_EX を使ってください。

flags には読み書きアクセス可能なら 0 で、読み出し専用なら READONLY を設定します。 typeT_STRING を使うと、 READONLY 扱いになります。 T_OBJECT メンバと T_OBJECT_EX メンバだけが削除できます (NULL が代入されます)。

PyGetSetDef

Structure to define property-like access for a type. See also description of the PyTypeObject.tp_getset slot.

フィールド C の型 意味
名前 char * attribute name
get getter C Function to get the attribute
集合 setter optional C function to set or delete the attribute, if omitted the attribute is readonly
doc char * optional docstring
closure void * optional function pointer, providing additional data for getter and setter

The get function takes one PyObject* parameter (the instance) and a function pointer (the associated closure):

typedef PyObject *(*getter)(PyObject *, void *);

It should return a new reference on success or NULL with a set exception on failure.

set functions take two PyObject* parameters (the instance and the value to be set) and a function pointer (the associated closure):

typedef int (*setter)(PyObject *, PyObject *, void *);

In case the attribute should be deleted the second parameter is NULL. Should return 0 on success or -1 with a set exception on failure.