引数の解析と値の構築
これらの関数は、独自の拡張関数とメソッドを作成するときに役立ちます。 追加情報と例は、 Pythonインタープリターの拡張と埋め込みにあります。
説明されているこれらの関数の最初の3つ、 PyArg_ParseTuple()、 PyArg_ParseTupleAndKeywords()、および PyArg_Parse()は、すべて形式の文字列を使用します。期待される引数について関数に伝えるために使用されます。 フォーマット文字列は、これらの各関数に同じ構文を使用します。
フォーマット文字列は、0個以上の「フォーマットユニット」で構成されます。 フォーマットユニットは、1つのPythonオブジェクトを記述します。 これは通常、単一の文字または括弧で囲まれたフォーマット単位のシーケンスです。 いくつかの例外を除いて、括弧で囲まれたシーケンスではないフォーマット単位は、通常、これらの関数の単一のアドレス引数に対応します。 以下の説明では、引用符で囲まれた形式がフォーマット単位です。 (丸)括弧内のエントリは、フォーマット単位に一致するPythonオブジェクトタイプです。 [角かっこ]内のエントリは、アドレスを渡す必要があるC変数のタイプです。
これらの形式では、メモリの連続したチャンクとしてオブジェクトにアクセスできます。 返されたUnicodeまたはバイト領域にrawストレージを提供する必要はありません。 また、es
、es#
、et
、et#
形式を除いて、自分でメモリを解放する必要はありません。
s
(文字列またはUnicode)[const char *]Python文字列またはUnicodeオブジェクトを文字列へのCポインタに変換します。 文字列自体のストレージを提供してはなりません。 既存の文字列へのポインタは、アドレスを渡す文字ポインタ変数に格納されます。 C文字列はNULで終了します。 Python文字列には、埋め込まれたNULバイトを含めることはできません。 含まれている場合、
TypeError
例外が発生します。 Unicodeオブジェクトは、デフォルトのエンコーディングを使用してC文字列に変換されます。 この変換が失敗すると、UnicodeError
が発生します。s#
(文字列、Unicode、または任意の読み取りバッファ互換オブジェクト)[const char *、int(またはPy_ssize_t
、以下を参照)]s
のこのバリアントは、2つのC変数に格納します。最初の変数は文字列へのポインターで、2番目の変数はその長さです。 この場合、Python文字列にはnullバイトが埋め込まれている可能性があります。 Unicodeオブジェクトは、そのような変換が可能な場合、オブジェクトのデフォルトのエンコードされた文字列バージョンへのポインタを返します。 他のすべての読み取りバッファ互換オブジェクトは、生の内部データ表現への参照を返します。Python 2.5以降、長さ引数のタイプは、
Python.h
を含める前にマクロPY_SSIZE_T_CLEAN
を定義することで制御できます。 マクロが定義されている場合、長さはintではなくPy_ssize_t
です。s*
(文字列、Unicode、または任意のバッファ互換オブジェクト)[Py_buffer]s#
と同様に、このコードは呼び出し元によって提供されたPy_buffer構造体を埋めます。 バッファがロックされるため、呼び出し元はPy_BEGIN_ALLOW_THREADS
ブロック内でもバッファを使用できます。 呼び出し元は、データを処理した後、構造体を使用してPyBuffer_Release
を呼び出す責任があります。バージョン2.6の新機能。
z
(文字列、UnicodeまたはNone
)[const char *]s
と同様ですが、PythonオブジェクトがNone
の場合もあります。その場合、Cポインターは NULL に設定されます。z#
(文字列、Unicode、None
または任意の読み取りバッファー互換オブジェクト)[const char *、int]z
がs
に対してであるように、これはs#
に対してです。z*
(文字列、Unicode、None
または任意のバッファ互換オブジェクト)[Py_buffer]z
がs
に対してであるように、これはs*
に対してです。バージョン2.6の新機能。
u
(Unicode)[Py_UNICODE *]Python Unicodeオブジェクトを16ビットUnicode(UTF-16)データのNUL終了バッファーへのCポインターに変換します。
s
と同様に、Unicodeデータバッファ用のストレージを提供する必要はありません。 既存のUnicodeデータへのポインタは、アドレスを渡す Py_UNICODE ポインタ変数に格納されます。u#
(Unicode)[Py_UNICODE *、int]u
のこのバリアントは、2つのC変数に格納します。1つ目はUnicodeデータバッファーへのポインターで、2つ目はその長さです。 非Unicodeオブジェクトは、読み取りバッファポインタを Py_UNICODE 配列へのポインタとして解釈することによって処理されます。es
(文字列、Unicode、または文字バッファ互換オブジェクト)[const char * encoding、char ** buffer]s
のこのバリアントは、UnicodeおよびUnicodeに変換可能なオブジェクトを文字バッファーにエンコードするために使用されます。 これは、NULバイトが埋め込まれていないエンコードされたデータに対してのみ機能します。この形式には2つの引数が必要です。 1つ目は入力としてのみ使用され、エンコーディングの名前をNULで終了する文字列として指す
const char*
、または NULL である必要があります。この場合、デフォルトのエンコーディングが使用されます。 。 名前付きエンコーディングがPythonに認識されていない場合、例外が発生します。 2番目の引数はchar**
でなければなりません。 参照するポインタの値は、引数テキストの内容を含むバッファに設定されます。 テキストは、最初の引数で指定されたエンコーディングでエンコードされます。PyArg_ParseTuple()は、必要なサイズのバッファーを割り当て、エンコードされたデータをこのバッファーにコピーし、 * buffer を調整して新しく割り当てられたストレージを参照します。 呼び出し元は、 PyMem_Free()を呼び出して、使用後に割り当てられたバッファーを解放する責任があります。
et
(文字列、Unicode、または文字バッファ互換オブジェクト)[const char * encoding、char ** buffer]es
と同じですが、8ビットの文字列オブジェクトが再コーディングせずに渡される点が異なります。 代わりに、実装では、文字列オブジェクトがパラメータとして渡されたエンコーディングを使用することを前提としています。es#
(文字列、Unicode、または文字バッファー互換オブジェクト)[const char * encoding、char ** buffer、int * buffer_length]s#
のこのバリアントは、UnicodeおよびUnicodeに変換可能なオブジェクトを文字バッファーにエンコードするために使用されます。es
形式とは異なり、このバリアントでは、NUL文字を含む入力データを使用できます。3つの引数が必要です。 1つ目は入力としてのみ使用され、エンコーディングの名前をNULで終了する文字列として指す
const char*
、または NULL である必要があります。この場合、デフォルトのエンコーディングが使用されます。 。 名前付きエンコーディングがPythonに認識されていない場合、例外が発生します。 2番目の引数はchar**
でなければなりません。 参照するポインタの値は、引数テキストの内容を含むバッファに設定されます。 テキストは、最初の引数で指定されたエンコーディングでエンコードされます。 3番目の引数は整数へのポインタでなければなりません。 参照される整数は、出力バッファのバイト数に設定されます。操作には2つのモードがあります。
* buffer が NULL ポインターを指す場合、関数は必要なサイズのバッファーを割り当て、エンコードされたデータをこのバッファーにコピーし、 * buffer を参照するように設定します新しく割り当てられたストレージ。 呼び出し元は、 PyMem_Free()を呼び出して、使用後に割り当てられたバッファーを解放する責任があります。
* buffer が NULL 以外のポインター(既に割り当てられているバッファー)を指している場合、 PyArg_ParseTuple()はこの場所をバッファーとして使用し、初期値を解釈します。バッファサイズとして * buffer_length の。 次に、エンコードされたデータをバッファにコピーし、NULで終了します。 バッファが十分に大きくない場合、
TypeError
が設定されます。 注:Python 3.6以降、ValueError
が設定されます。どちらの場合も、 * buffer_length は、末尾のNULバイトを含まないエンコードされたデータの長さに設定されます。
et#
(文字列、Unicode、または文字バッファー互換オブジェクト)[const char * encoding、char ** buffer、int * buffer_length]文字列オブジェクトが再コーディングせずに渡されることを除いて、
es#
と同じです。 代わりに、実装では、文字列オブジェクトがパラメータとして渡されたエンコーディングを使用することを前提としています。b
(整数)[unsigned char]非負のPython整数を、C
unsigned char
に格納されているunsignedtinyintに変換します。B
(整数)[unsigned char]Python整数をオーバーフローチェックなしで小さなintに変換し、C
unsigned char
に格納します。バージョン2.3の新機能。
h
(整数)[short int]Python整数をC
short int
に変換します。H
(整数)[unsigned short int]オーバーフローチェックを行わずに、Python整数をC
unsigned short int
に変換します。バージョン2.3の新機能。
i
(整数)[int]Python整数をプレーンC
int
に変換します。I
(整数)[unsigned int]オーバーフローチェックを行わずに、Python整数をC
unsigned int
に変換します。バージョン2.3の新機能。
l
(整数)[long int]Python整数をC
long int
に変換します。k
(整数)[unsigned long]オーバーフローチェックを行わずに、Python整数または長整数をC
unsigned long
に変換します。バージョン2.3の新機能。
L
(整数)[PY_LONG_LONG]Python整数をC
long long
に変換します。 この形式は、long long
(またはWindowsでは_int64
)をサポートするプラットフォームでのみ使用できます。K
(整数)[unsigned PY_LONG_LONG]オーバーフローチェックを行わずに、Python整数または長整数をC
unsigned long long
に変換します。 この形式は、unsigned long long
(またはWindowsではunsigned _int64
)をサポートするプラットフォームでのみ使用できます。バージョン2.3の新機能。
n
(整数)[Py_ssize_t]Python整数または長整数をC
Py_ssize_t
に変換します。バージョン2.5の新機能。
c
(長さ1の文字列)[char]長さ1の文字列として表されるPython文字をC
char
に変換します。f
(フロート)[フロート]Python浮動小数点数をC
float
に変換します。d
(float)[double]Python浮動小数点数をC
double
に変換します。D
(複合)[Py_complex]Pythonの複素数をC Py_complex 構造に変換します。
O
(オブジェクト)[PyObject *]Pythonオブジェクト(変換なし)をCオブジェクトポインターに格納します。 したがって、Cプログラムは、渡された実際のオブジェクトを受け取ります。 オブジェクトの参照カウントは増加しません。 格納されているポインタは NULL ではありません。
O!
(オブジェクト)[ typeobject 、PyObject *]PythonオブジェクトをCオブジェクトポインタに格納します。 これは
O
に似ていますが、2つのC引数を取ります。1つ目はPython型オブジェクトのアドレス、2つ目は(PyObject*
型の)C変数のアドレスです。オブジェクトポインタが格納されます。 Pythonオブジェクトに必要なタイプがない場合、TypeError
が発生します。O&
(オブジェクト)[コンバーター、すべて]コンバーター関数を使用してPythonオブジェクトをC変数に変換します。 これには2つの引数があります。1つ目は関数、2つ目は
void *
に変換された(任意の型の)C変数のアドレスです。 コンバーター関数は次のように呼び出されます。status = converter(object, address);
ここで、 object は変換されるPythonオブジェクトであり、 address は
PyArg_Parse*()
関数に渡されたvoid*
引数です。 返されるステータスは、変換が成功した場合は1
になり、変換が失敗した場合は0
になります。 変換が失敗した場合、コンバーター関数は例外を発生させ、アドレスの内容を変更しないままにする必要があります。S
(文字列)[PyStringObject *]O
と同様ですが、Pythonオブジェクトが文字列オブジェクトである必要があります。 オブジェクトが文字列オブジェクトでない場合、TypeError
を発生させます。 C変数は、PyObject*
として宣言することもできます。U
(Unicode文字列)[PyUnicodeObject *]O
と同様ですが、PythonオブジェクトがUnicodeオブジェクトである必要があります。 オブジェクトがUnicodeオブジェクトでない場合は、TypeError
を発生させます。 C変数は、PyObject*
として宣言することもできます。t#
(読み取り専用文字バッファー)[char *、int]s#
と同様ですが、読み取り専用バッファインターフェイスを実装するすべてのオブジェクトを受け入れます。char*
変数はバッファーの最初のバイトを指すように設定され、int
はバッファーの長さに設定されます。 単一セグメントのバッファオブジェクトのみが受け入れられます。TypeError
は他のすべてのために発生します。w
(読み取り/書き込み文字バッファー)[char *]s
に似ていますが、読み取り/書き込みバッファーインターフェイスを実装するすべてのオブジェクトを受け入れます。 呼び出し元は、他の方法でバッファーの長さを決定するか、代わりにw#
を使用する必要があります。 単一セグメントのバッファオブジェクトのみが受け入れられます。TypeError
は他のすべてのために発生します。w#
(読み取り/書き込み文字バッファー)[char *、Py_ssize_t]s#
と同様ですが、読み取り/書き込みバッファーインターフェイスを実装するすべてのオブジェクトを受け入れます。char *
変数はバッファーの最初のバイトを指すように設定され、Py_ssize_t
はバッファーの長さに設定されます。 単一セグメントのバッファオブジェクトのみが受け入れられます。TypeError
は他のすべてのために発生します。w*
(読み取り/書き込みバイト指向バッファー)[Py_buffer]これは
w
に対するものであり、s*
に対するものはs
に対するものです。バージョン2.6の新機能。
(items)
(タプル)[マッチングアイテム]オブジェクトは、長さが items のフォーマット単位の数であるPythonシーケンスである必要があります。 C引数は、 items の個々のフォーマット単位に対応している必要があります。 シーケンスのフォーマット単位はネストできます。
ノート
Pythonバージョン1.5.2より前は、このフォーマット指定子は、任意のシーケンスではなく、個々のパラメーターを含むタプルのみを受け入れていました。 以前に
TypeError
がここで発生したコードは、例外なく続行できるようになりました。 これは、既存のコードでは問題になるとは思われません。
整数が要求された場所にPythonの長整数を渡すことができます。 ただし、適切な範囲チェックは行われません。受信フィールドが小さすぎて値を受信できない場合、最上位ビットはサイレントに切り捨てられます(実際、セマンティクスはCのダウンキャストから継承されます。マイレージは異なる場合があります)。
他のいくつかの文字は、フォーマット文字列で意味を持ちます。 これらは、ネストされた括弧内では発生しない場合があります。 彼らです:
|
- Python引数リストの残りの引数がオプションであることを示します。 オプションの引数に対応するC変数は、デフォルト値に初期化する必要があります—オプションの引数が指定されていない場合、 PyArg_ParseTuple()は対応するC変数の内容に触れません。
:
- フォーマット単位のリストはここで終わります。 コロンの後の文字列は、エラーメッセージの関数名として使用されます( PyArg_ParseTuple()が発生する例外の「関連付けられた値」)。
;
- フォーマット単位のリストはここで終わります。 セミコロンの後の文字列は、デフォルトのエラーメッセージのの代わりにエラーメッセージとして使用されます。
:
と;
は相互に除外します。
呼び出し元に提供されるPythonオブジェクト参照は、借用参照であることに注意してください。 参照カウントをデクリメントしないでください!
これらの関数に渡される追加の引数は、タイプがフォーマット文字列によって決定される変数のアドレスである必要があります。 これらは、入力タプルからの値を格納するために使用されます。 上記のフォーマット単位のリストで説明されているように、これらのパラメーターが入力値として使用される場合がいくつかあります。 その場合、対応するフォーマット単位に指定されているものと一致する必要があります。
変換を成功させるには、 arg オブジェクトがフォーマットと一致し、フォーマットが使い果たされている必要があります。 成功すると、PyArg_Parse*()
関数はtrueを返します。それ以外の場合は、falseを返し、適切な例外を発生させます。 いずれかのフォーマット単位での変換失敗によりPyArg_Parse*()
機能が失敗した場合、それに対応するアドレス以降のフォーマット単位の変数はそのままになります。
- int PyArg_ParseTuple(PyObject *args, const char *format, ...)
- 位置パラメーターのみをローカル変数に取り込む関数のパラメーターを解析します。 成功するとtrueを返します。 失敗すると、falseを返し、適切な例外を発生させます。
- int PyArg_VaParse(PyObject *args, const char *format, va_list vargs)
- PyArg_ParseTuple()と同じですが、可変数の引数ではなくva_listを受け入れる点が異なります。
- int PyArg_ParseTupleAndKeywords(PyObject *args, PyObject *kw, const char *format, char *keywords[], ...)
- 位置パラメーターとキーワードパラメーターの両方をローカル変数に取り込む関数のパラメーターを解析します。 成功するとtrueを返します。 失敗すると、falseを返し、適切な例外を発生させます。
- int PyArg_VaParseTupleAndKeywords(PyObject *args, PyObject *kw, const char *format, char *keywords[], va_list vargs)
- PyArg_ParseTupleAndKeywords()と同じですが、可変数の引数ではなくva_listを受け入れる点が異なります。
- int PyArg_Parse(PyObject *args, const char *format, ...)
- 「古いスタイル」の関数の引数リストを分解するために使用される関数—これらは METH_OLDARGS パラメーター解析メソッドを使用する関数です。 これは、新しいコードでのパラメーター解析での使用は推奨されていません。また、標準インタープリターのほとんどのコードは、その目的でこれを使用しないように変更されています。 ただし、他のタプルを分解するための便利な方法であり続け、その目的で引き続き使用される可能性があります。
- int PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, ...)
引数のタイプを指定するためにフォーマット文字列を使用しない、より単純な形式のパラメーター検索。 このメソッドを使用してパラメーターを取得する関数は、関数テーブルまたはメソッドテーブルで METH_VARARGS として宣言する必要があります。 実際のパラメーターを含むタプルは、 args として渡す必要があります。 実際にはタプルである必要があります。 タプルの長さは、 min 以上、 max 以下である必要があります。 min と max は同じである可能性があります。 追加の引数を関数に渡す必要があります。各引数は、
PyObject*
変数へのポインターである必要があります。 これらには、 args の値が入力されます。 借用した参照が含まれます。 args で指定されていないオプションのパラメーターに対応する変数は入力されません。 これらは、呼び出し元が初期化する必要があります。 この関数は、成功した場合はtrueを返し、 args がタプルでない場合、または要素の数が間違っている場合はfalseを返します。 障害が発生した場合は例外が設定されます。これは、弱参照用の
_weakref
ヘルパーモジュールのソースから取得したこの関数の使用例です。static PyObject * weakref_ref(PyObject *self, PyObject *args) { PyObject *object; PyObject *callback = NULL; PyObject *result = NULL; if (PyArg_UnpackTuple(args, "ref", 1, 2, &object, &callback)) { result = PyWeakref_NewRef(object, callback); } return result; }
この例での PyArg_UnpackTuple()の呼び出しは、 PyArg_ParseTuple()のこの呼び出しと完全に同等です。
PyArg_ParseTuple(args, "O|O:ref", &object, &callback)
バージョン2.2の新機能。
バージョン2.5で変更:この関数は、 min および max に
int
タイプを使用していました。 これには、64ビットシステムを適切にサポートするためにコードの変更が必要になる場合があります。
- PyObject *Py_BuildValue(const char *format, ...)
PyArg_Parse*()
ファミリーの関数で受け入れられるものと同様のフォーマット文字列と一連の値に基づいて、新しい値を作成します。 エラーの場合は値または NULL を返します。 NULL が返されると、例外が発生します。Py_BuildValue()は、常にタプルを作成するとは限りません。 フォーマット文字列に2つ以上のフォーマット単位が含まれている場合にのみ、タプルを作成します。 フォーマット文字列が空の場合、
None
を返します。 フォーマットユニットが1つだけ含まれている場合は、そのフォーマットユニットによって記述されているオブジェクトを返します。 サイズ0
または1のタプルを強制的に返すには、フォーマット文字列を括弧で囲みます。s
およびs#
形式の場合と同様に、メモリバッファがパラメータとして渡され、ビルドオブジェクトにデータが提供されると、必要なデータがコピーされます。 呼び出し元によって提供されたバッファーは、 Py_BuildValue()によって作成されたオブジェクトによって参照されることはありません。 つまり、コードがmalloc()
を呼び出し、割り当てられたメモリを Py_BuildValue()に渡す場合、コードは Py_BuildValueでそのメモリのfree()
を呼び出す必要があります。 ()が戻ります。以下の説明では、引用符で囲まれた形式がフォーマット単位です。 (丸)括弧内のエントリは、フォーマットユニットが返すPythonオブジェクトタイプです。 [角かっこ]内のエントリは、渡されるC値のタイプです。
スペース、タブ、コロン、およびコンマの文字は、フォーマット文字列では無視されます(ただし、
s#
などのフォーマット単位内では無視されます)。 これを使用して、長い形式の文字列を少し読みやすくすることができます。s
(文字列)[char *]nullで終了するC文字列をPythonオブジェクトに変換します。 C文字列ポインタが NULL の場合、
None
が使用されます。s#
(文字列)[char *、int]C文字列とその長さをPythonオブジェクトに変換します。 C文字列ポインタが NULL の場合、長さは無視され、
None
が返されます。z
(文字列またはNone
)[char *]s
と同じです。z#
(文字列またはNone
)[char *、int]s#
と同じです。u
(Unicode文字列)[Py_UNICODE *]Unicode(UCS-2またはUCS-4)データのnullで終了するバッファーをPythonUnicodeオブジェクトに変換します。 Unicodeバッファポインタが NULL の場合、
None
が返されます。u#
(Unicode文字列)[Py_UNICODE *、int]Unicode(UCS-2またはUCS-4)データバッファーとその長さをPythonUnicodeオブジェクトに変換します。 Unicodeバッファポインタが NULL の場合、長さは無視され、
None
が返されます。i
(整数)[int]プレーンC
int
をPython整数オブジェクトに変換します。b
(整数)[char]プレーンC
char
をPython整数オブジェクトに変換します。h
(整数)[short int]プレーンC
short int
をPython整数オブジェクトに変換します。l
(整数)[long int]C
long int
をPython整数オブジェクトに変換します。B
(整数)[unsigned char]C
unsigned char
をPython整数オブジェクトに変換します。H
(整数)[unsigned short int]C
unsigned short int
をPython整数オブジェクトに変換します。I
(integer / long)[unsigned int]C
unsigned int
がsys.maxint
より大きい場合は、Python整数オブジェクトまたはPython長整数オブジェクトに変換します。k
(integer / long)[unsigned long]C
unsigned long
がsys.maxint
より大きい場合は、Python整数オブジェクトまたはPython長整数オブジェクトに変換します。L
(長い)[PY_LONG_LONG]C
long long
をPythonの長整数オブジェクトに変換します。long long
をサポートするプラットフォームでのみ使用できます。K
(long)[unsigned PY_LONG_LONG]C
unsigned long long
をPythonの長整数オブジェクトに変換します。unsigned long long
をサポートするプラットフォームでのみ使用できます。n
(int)[Py_ssize_t]C
Py_ssize_t
をPython整数または長整数に変換します。バージョン2.5の新機能。
c
(長さ1の文字列)[char]文字を表すC
int
を長さ1のPython文字列に変換します。d
(float)[double]C
double
をPython浮動小数点数に変換します。f
(フロート)[フロート]d
と同じです。D
(複雑)[Py_complex *]C Py_complex 構造体をPythonの複素数に変換します。
O
(オブジェクト)[PyObject *]Pythonオブジェクトをそのまま渡します(1ずつインクリメントされる参照カウントを除く)。 渡されたオブジェクトが NULL ポインターの場合、引数を生成する呼び出しでエラーが検出され、例外が設定されたことが原因であると考えられます。 したがって、 Py_BuildValue()は NULL を返しますが、例外は発生しません。 まだ例外が発生していない場合は、
SystemError
が設定されます。S
(オブジェクト)[PyObject *]O
と同じです。N
(オブジェクト)[PyObject *]O
と同じですが、オブジェクトの参照カウントがインクリメントされない点が異なります。 引数リスト内のオブジェクトコンストラクターの呼び出しによってオブジェクトが作成される場合に役立ちます。O&
(オブジェクト)[コンバーター、すべて]コンバーター関数を使用して、すべてをPythonオブジェクトに変換します。 この関数は、 anything (
void *
と互換性がある必要があります)を引数として呼び出され、「新しい」Pythonオブジェクトを返すか、エラーが発生した場合は NULL を返す必要があります。 。(items)
(タプル)[マッチングアイテム]C値のシーケンスを同じ数のアイテムを持つPythonタプルに変換します。
[items]
(リスト)[マッチングアイテム]C値のシーケンスを同じ数のアイテムを持つPythonリストに変換します。
{items}
(辞書)[マッチングアイテム]C値のシーケンスをPython辞書に変換します。 連続するC値の各ペアは、それぞれキーと値として機能する1つの項目をディクショナリに追加します。
フォーマット文字列にエラーがある場合、
SystemError
例外が設定され、 NULL が返されます。
- PyObject *Py_VaBuildValue(const char *format, va_list vargs)
- Py_BuildValue()と同じですが、可変数の引数ではなくva_listを受け入れる点が異なります。