Python/C関数実行とPyObject
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
[[Pythonを読む]]
#contents
*はじめに [#wbc2cbcd]
__build_class__が実行される様を見ていきます。以前にも見ま...
#code(C){{
TARGET(CALL_FUNCTION) {
PyObject **sp, *res;
PCALL(PCALL_ALL);
sp = stack_pointer;
res = call_function(&sp, oparg, NULL);
stack_pointer = sp;
PUSH(res);
if (res == NULL) {
goto error;
}
DISPATCH();
}
}}
前はcall_functionの先は概要だけ説明しましたが今回はこの先...
*call_function (Python/ceval.c) [#q76328c9]
call_functionはバイトコード実行と同じceval.cに書かれてい...
#code(C){{
static PyObject *
call_function(PyObject ***pp_stack, Py_ssize_t oparg, PyO...
{
PyObject **pfunc = (*pp_stack) - oparg - 1;
PyObject *func = *pfunc;
PyObject *x, *w;
Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_...
Py_ssize_t nargs = oparg - nkwargs;
PyObject **stack;
/* Always dispatch PyCFunction first, because these are
presumed to be the most frequent callable object.
*/
if (PyCFunction_Check(func)) {
PyThreadState *tstate = PyThreadState_GET();
PCALL(PCALL_CFUNCTION);
stack = (*pp_stack) - nargs - nkwargs;
C_TRACE(x, _PyCFunction_FastCallKeywords(func, st...
}
else {
// Pythonで書かれた関数。省略
}
assert((x != NULL) ^ (PyErr_Occurred() != NULL));
/* Clear the stack of the function object. Also remo...
the arguments in case they weren't consumed already
(fast_function() and err_args() leave them on the ...
*/
while ((*pp_stack) > pfunc) {
w = EXT_POP(*pp_stack);
Py_DECREF(w);
PCALL(PCALL_POP);
}
return x;
}
}}
__build_class__の実装はCで書かれているので今回はifの部分...
Cで実装された関数を実行する_PyCFunction_FastCallKeywords...
*PyObject (Include/object.h) [#hd51e3d0]
PyObjectはその名の通りPythonオブジェクトのC表現です。
#code(C){{
typedef struct _object {
_PyObject_HEAD_EXTRA
Py_ssize_t ob_refcnt;
struct _typeobject *ob_type;
} PyObject;
}}
_PyObject_HEAD_EXTRAはデバッグオプション付きでビルドされ...
TypeObjectを見る前に、__build_class__はPyCFunctionObject...
#code(C){{
typedef struct {
PyObject_HEAD
PyMethodDef *m_ml; /* Description of the C function t...
PyObject *m_self; /* Passed as 'self' arg to the C...
PyObject *m_module; /* The __module__ attribute, c...
PyObject *m_weakreflist; /* List of weak reference...
} PyCFunctionObject;
}}
PyObject_HEADの定義はInclude/object.hに戻って、
#code(C){{
/* PyObject_HEAD defines the initial segment of every PyO...
#define PyObject_HEAD PyObject ob_base;
}}
つまり、PyCFunctionObjectの先頭部分はPyObjectということに...
#code(C){{
typedef struct {
Py_ssize_t ob_refcnt;
struct _typeobject *ob_type;
PyMethodDef *m_ml;
PyObject *m_self;
PyObject *m_module;
PyObject *m_weakreflist;
} PyCFunctionObject;
}}
全てのオブジェクト表現が共通のヘッダを持っているため、操...
ちなみに、PyCFunction_Checkの実装は以下の通りです。
#code(C){{
#define PyCFunction_Check(op) (Py_TYPE(op) == &PyCFunctio...
}}
Py_TYPEはob_typeメンバを取り出すマクロです。
*PyTypeObject (Include/object.h) [#b227591f]
さて次にPyTypeObjectです。
#code(C){{
typedef struct _typeobject {
PyObject_VAR_HEAD
const char *tp_name; /* For printing, in format "<mod...
Py_ssize_t tp_basicsize, tp_itemsize; /* For allocati...
/* 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_...
or tp_reserved (Pytho...
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 compatib...
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 feat...
unsigned long tp_flags;
const char *tp_doc; /* Documentation string */
/* Assigned meaning in release 2.0 */
/* call function for all accessible objects */
traverseproc tp_traverse;
/* delete references to contained objects */
inquiry tp_clear;
/* Assigned meaning in release 2.1 */
/* 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...
unsigned int tp_version_tag;
destructor tp_finalize;
} PyTypeObject;
}}
長い、ってところですがメンバについて詳しいことは次回以降...
#code(C){{
PyTypeObject PyCFunction_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"builtin_function_or_method",
sizeof(PyCFunctionObject),
0,
(destructor)meth_dealloc, /* tp_dea...
0, /* tp_pri...
0, /* tp_get...
0, /* tp_set...
0, /* tp_res...
(reprfunc)meth_repr, /* tp_rep...
0, /* tp_as_...
0, /* tp_as_...
0, /* tp_as_...
(hashfunc)meth_hash, /* tp_has...
PyCFunction_Call, /* tp_cal...
0, /* tp_str...
PyObject_GenericGetAttr, /* tp_get...
0, /* tp_set...
0, /* tp_as_...
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
0, /* tp_doc...
(traverseproc)meth_traverse, /* tp_tra...
0, /* tp_cle...
meth_richcompare, /* tp_ric...
offsetof(PyCFunctionObject, m_weakreflist), /* tp_wea...
0, /* tp_ite...
0, /* tp_ite...
meth_methods, /* tp_met...
meth_members, /* tp_mem...
meth_getsets, /* tp_get...
0, /* tp_bas...
0, /* tp_dic...
};
}}
今回の本筋ではありませんが説明しないわけにもいかないので...
で、ともかくPyCFunction型が定義されました。
**PyObjectとPyTypeObjectの関連付け [#kdc4b44d]
大体わかってきましたがPyTypeObjectはPyObjectの型を表すオ...
#code(C){{
PyObject *
PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObje...
{
PyCFunctionObject *op;
op = free_list;
if (op != NULL) {
free_list = (PyCFunctionObject *)(op->m_self);
(void)PyObject_INIT(op, &PyCFunction_Type);
numfree--;
}
else {
op = PyObject_GC_New(PyCFunctionObject, &PyCFunct...
if (op == NULL)
return NULL;
}
op->m_weakreflist = NULL;
op->m_ml = ml;
Py_XINCREF(self);
op->m_self = self;
Py_XINCREF(module);
op->m_module = module;
_PyObject_GC_TRACK(op);
return (PyObject *)op;
}
}}
PyObject_GC_New、Include/objimpl.hを経由して実体はModule/...
#code(C){{
_PyObject_GC_New(PyTypeObject *tp)
{
PyObject *op = _PyObject_GC_Malloc(_PyObject_SIZE(tp));
if (op != NULL)
op = PyObject_INIT(op, tp);
return op;
}
}}
PyObject_INITはまたInclude/objimpl.hに戻ります。
#code(C){{
#define PyObject_INIT(op, typeobj) \
( Py_TYPE(op) = (typeobj), _Py_NewReference((PyObject...
}}
というわけでPyObjectとPyTypeObjectが関連付けられました。
*_PyCFunction_FastCallKeywords (Objects/methodobject.c) [...
長くなりましたがPyObjectについて確認できたのでオブジェク...
#code(C){{
PyObject *
_PyCFunction_FastCallKeywords(PyObject *func, PyObject **...
Py_ssize_t nargs, PyObject ...
{
PyObject *kwdict, *result;
Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_...
/* kwnames must only contains str strings, no subclas...
be unique */
if (nkwargs > 0) {
kwdict = _PyStack_AsDict(stack + nargs, kwnames);
if (kwdict == NULL) {
return NULL;
}
}
else {
kwdict = NULL;
}
result = _PyCFunction_FastCallDict(func, stack, nargs...
Py_XDECREF(kwdict);
return result;
}
}}
今回はnkwargsは0なのでそのまま_PyCFunction_FastCallDictへ。
長いので実行される部分以外は省略。
#code(C){{
PyObject *
_PyCFunction_FastCallDict(PyObject *func_obj, PyObject **...
PyObject *kwargs)
{
PyCFunctionObject *func = (PyCFunctionObject*)func_obj;
PyCFunction meth = PyCFunction_GET_FUNCTION(func);
PyObject *self = PyCFunction_GET_SELF(func);
PyObject *result;
int flags;
/* _PyCFunction_FastCallDict() must not be called wit...
because it may clear it (directly or indirectly) a...
caller loses its exception */
flags = PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | ...
switch (flags)
{
case METH_NOARGS:
// 省略
case METH_O:
// 省略
case METH_VARARGS:
case METH_VARARGS | METH_KEYWORDS:
{
/* Slow-path: create a temporary tuple */
PyObject *tuple;
if (!(flags & METH_KEYWORDS) && kwargs != NULL &&...
PyErr_Format(PyExc_TypeError,
"%.200s() takes no keyword argum...
func->m_ml->ml_name);
return NULL;
}
tuple = _PyStack_AsTuple(args, nargs);
if (tuple == NULL) {
return NULL;
}
if (flags & METH_KEYWORDS) {
result = (*(PyCFunctionWithKeywords)meth) (se...
}
else {
result = (*meth) (self, tuple);
}
Py_DECREF(tuple);
break;
}
case METH_FASTCALL:
// 省略
default:
PyErr_SetString(PyExc_SystemError,
"Bad call flags in PyCFunction_Ca...
"METH_OLDARGS is no longer suppor...
return NULL;
}
result = _Py_CheckFunctionResult(func_obj, result, NU...
return result;
}
}}
というわけで、Python関数に対応するC言語の関数が実行される...
*おわりに [#oc6198da]
今回は関数実行をスタートにPyObjectについて見ていきました。
本当はPyTypeObjectについてもう少し触れようと思ったのです...
ともかくこれでようやく__build_class__に対するbuiltin___bu...
終了行:
[[Pythonを読む]]
#contents
*はじめに [#wbc2cbcd]
__build_class__が実行される様を見ていきます。以前にも見ま...
#code(C){{
TARGET(CALL_FUNCTION) {
PyObject **sp, *res;
PCALL(PCALL_ALL);
sp = stack_pointer;
res = call_function(&sp, oparg, NULL);
stack_pointer = sp;
PUSH(res);
if (res == NULL) {
goto error;
}
DISPATCH();
}
}}
前はcall_functionの先は概要だけ説明しましたが今回はこの先...
*call_function (Python/ceval.c) [#q76328c9]
call_functionはバイトコード実行と同じceval.cに書かれてい...
#code(C){{
static PyObject *
call_function(PyObject ***pp_stack, Py_ssize_t oparg, PyO...
{
PyObject **pfunc = (*pp_stack) - oparg - 1;
PyObject *func = *pfunc;
PyObject *x, *w;
Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_...
Py_ssize_t nargs = oparg - nkwargs;
PyObject **stack;
/* Always dispatch PyCFunction first, because these are
presumed to be the most frequent callable object.
*/
if (PyCFunction_Check(func)) {
PyThreadState *tstate = PyThreadState_GET();
PCALL(PCALL_CFUNCTION);
stack = (*pp_stack) - nargs - nkwargs;
C_TRACE(x, _PyCFunction_FastCallKeywords(func, st...
}
else {
// Pythonで書かれた関数。省略
}
assert((x != NULL) ^ (PyErr_Occurred() != NULL));
/* Clear the stack of the function object. Also remo...
the arguments in case they weren't consumed already
(fast_function() and err_args() leave them on the ...
*/
while ((*pp_stack) > pfunc) {
w = EXT_POP(*pp_stack);
Py_DECREF(w);
PCALL(PCALL_POP);
}
return x;
}
}}
__build_class__の実装はCで書かれているので今回はifの部分...
Cで実装された関数を実行する_PyCFunction_FastCallKeywords...
*PyObject (Include/object.h) [#hd51e3d0]
PyObjectはその名の通りPythonオブジェクトのC表現です。
#code(C){{
typedef struct _object {
_PyObject_HEAD_EXTRA
Py_ssize_t ob_refcnt;
struct _typeobject *ob_type;
} PyObject;
}}
_PyObject_HEAD_EXTRAはデバッグオプション付きでビルドされ...
TypeObjectを見る前に、__build_class__はPyCFunctionObject...
#code(C){{
typedef struct {
PyObject_HEAD
PyMethodDef *m_ml; /* Description of the C function t...
PyObject *m_self; /* Passed as 'self' arg to the C...
PyObject *m_module; /* The __module__ attribute, c...
PyObject *m_weakreflist; /* List of weak reference...
} PyCFunctionObject;
}}
PyObject_HEADの定義はInclude/object.hに戻って、
#code(C){{
/* PyObject_HEAD defines the initial segment of every PyO...
#define PyObject_HEAD PyObject ob_base;
}}
つまり、PyCFunctionObjectの先頭部分はPyObjectということに...
#code(C){{
typedef struct {
Py_ssize_t ob_refcnt;
struct _typeobject *ob_type;
PyMethodDef *m_ml;
PyObject *m_self;
PyObject *m_module;
PyObject *m_weakreflist;
} PyCFunctionObject;
}}
全てのオブジェクト表現が共通のヘッダを持っているため、操...
ちなみに、PyCFunction_Checkの実装は以下の通りです。
#code(C){{
#define PyCFunction_Check(op) (Py_TYPE(op) == &PyCFunctio...
}}
Py_TYPEはob_typeメンバを取り出すマクロです。
*PyTypeObject (Include/object.h) [#b227591f]
さて次にPyTypeObjectです。
#code(C){{
typedef struct _typeobject {
PyObject_VAR_HEAD
const char *tp_name; /* For printing, in format "<mod...
Py_ssize_t tp_basicsize, tp_itemsize; /* For allocati...
/* 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_...
or tp_reserved (Pytho...
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 compatib...
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 feat...
unsigned long tp_flags;
const char *tp_doc; /* Documentation string */
/* Assigned meaning in release 2.0 */
/* call function for all accessible objects */
traverseproc tp_traverse;
/* delete references to contained objects */
inquiry tp_clear;
/* Assigned meaning in release 2.1 */
/* 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...
unsigned int tp_version_tag;
destructor tp_finalize;
} PyTypeObject;
}}
長い、ってところですがメンバについて詳しいことは次回以降...
#code(C){{
PyTypeObject PyCFunction_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"builtin_function_or_method",
sizeof(PyCFunctionObject),
0,
(destructor)meth_dealloc, /* tp_dea...
0, /* tp_pri...
0, /* tp_get...
0, /* tp_set...
0, /* tp_res...
(reprfunc)meth_repr, /* tp_rep...
0, /* tp_as_...
0, /* tp_as_...
0, /* tp_as_...
(hashfunc)meth_hash, /* tp_has...
PyCFunction_Call, /* tp_cal...
0, /* tp_str...
PyObject_GenericGetAttr, /* tp_get...
0, /* tp_set...
0, /* tp_as_...
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
0, /* tp_doc...
(traverseproc)meth_traverse, /* tp_tra...
0, /* tp_cle...
meth_richcompare, /* tp_ric...
offsetof(PyCFunctionObject, m_weakreflist), /* tp_wea...
0, /* tp_ite...
0, /* tp_ite...
meth_methods, /* tp_met...
meth_members, /* tp_mem...
meth_getsets, /* tp_get...
0, /* tp_bas...
0, /* tp_dic...
};
}}
今回の本筋ではありませんが説明しないわけにもいかないので...
で、ともかくPyCFunction型が定義されました。
**PyObjectとPyTypeObjectの関連付け [#kdc4b44d]
大体わかってきましたがPyTypeObjectはPyObjectの型を表すオ...
#code(C){{
PyObject *
PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObje...
{
PyCFunctionObject *op;
op = free_list;
if (op != NULL) {
free_list = (PyCFunctionObject *)(op->m_self);
(void)PyObject_INIT(op, &PyCFunction_Type);
numfree--;
}
else {
op = PyObject_GC_New(PyCFunctionObject, &PyCFunct...
if (op == NULL)
return NULL;
}
op->m_weakreflist = NULL;
op->m_ml = ml;
Py_XINCREF(self);
op->m_self = self;
Py_XINCREF(module);
op->m_module = module;
_PyObject_GC_TRACK(op);
return (PyObject *)op;
}
}}
PyObject_GC_New、Include/objimpl.hを経由して実体はModule/...
#code(C){{
_PyObject_GC_New(PyTypeObject *tp)
{
PyObject *op = _PyObject_GC_Malloc(_PyObject_SIZE(tp));
if (op != NULL)
op = PyObject_INIT(op, tp);
return op;
}
}}
PyObject_INITはまたInclude/objimpl.hに戻ります。
#code(C){{
#define PyObject_INIT(op, typeobj) \
( Py_TYPE(op) = (typeobj), _Py_NewReference((PyObject...
}}
というわけでPyObjectとPyTypeObjectが関連付けられました。
*_PyCFunction_FastCallKeywords (Objects/methodobject.c) [...
長くなりましたがPyObjectについて確認できたのでオブジェク...
#code(C){{
PyObject *
_PyCFunction_FastCallKeywords(PyObject *func, PyObject **...
Py_ssize_t nargs, PyObject ...
{
PyObject *kwdict, *result;
Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_...
/* kwnames must only contains str strings, no subclas...
be unique */
if (nkwargs > 0) {
kwdict = _PyStack_AsDict(stack + nargs, kwnames);
if (kwdict == NULL) {
return NULL;
}
}
else {
kwdict = NULL;
}
result = _PyCFunction_FastCallDict(func, stack, nargs...
Py_XDECREF(kwdict);
return result;
}
}}
今回はnkwargsは0なのでそのまま_PyCFunction_FastCallDictへ。
長いので実行される部分以外は省略。
#code(C){{
PyObject *
_PyCFunction_FastCallDict(PyObject *func_obj, PyObject **...
PyObject *kwargs)
{
PyCFunctionObject *func = (PyCFunctionObject*)func_obj;
PyCFunction meth = PyCFunction_GET_FUNCTION(func);
PyObject *self = PyCFunction_GET_SELF(func);
PyObject *result;
int flags;
/* _PyCFunction_FastCallDict() must not be called wit...
because it may clear it (directly or indirectly) a...
caller loses its exception */
flags = PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | ...
switch (flags)
{
case METH_NOARGS:
// 省略
case METH_O:
// 省略
case METH_VARARGS:
case METH_VARARGS | METH_KEYWORDS:
{
/* Slow-path: create a temporary tuple */
PyObject *tuple;
if (!(flags & METH_KEYWORDS) && kwargs != NULL &&...
PyErr_Format(PyExc_TypeError,
"%.200s() takes no keyword argum...
func->m_ml->ml_name);
return NULL;
}
tuple = _PyStack_AsTuple(args, nargs);
if (tuple == NULL) {
return NULL;
}
if (flags & METH_KEYWORDS) {
result = (*(PyCFunctionWithKeywords)meth) (se...
}
else {
result = (*meth) (self, tuple);
}
Py_DECREF(tuple);
break;
}
case METH_FASTCALL:
// 省略
default:
PyErr_SetString(PyExc_SystemError,
"Bad call flags in PyCFunction_Ca...
"METH_OLDARGS is no longer suppor...
return NULL;
}
result = _Py_CheckFunctionResult(func_obj, result, NU...
return result;
}
}}
というわけで、Python関数に対応するC言語の関数が実行される...
*おわりに [#oc6198da]
今回は関数実行をスタートにPyObjectについて見ていきました。
本当はPyTypeObjectについてもう少し触れようと思ったのです...
ともかくこれでようやく__build_class__に対するbuiltin___bu...
ページ名: