C の Python インスタンス メソッド
-
21-09-2019 - |
質問
次の Python (3.x) コードを考えてみましょう。
class Foo(object):
def bar(self):
pass
foo = Foo()
同じ機能を C で記述するにはどうすればよいでしょうか?
つまり、C でメソッドを使用してオブジェクトを作成するにはどうすればよいでしょうか?そしてそこからインスタンスを作成しますか?
編集:あ、ごめんなさい!私は Python C API を介した同じ機能を意味しました。C API 経由で Python メソッドを作成するにはどうすればよいですか?何かのようなもの:
PyObject *Foo = ?????;
PyMethod??? *bar = ????;
解決
ここで http://nedbatchelder.com/text/whirlext.html <から適応単純なクラス(です/ A> 3.xの):
#include "Python.h"
#include "structmember.h"
// The CountDict type.
typedef struct {
PyObject_HEAD
PyObject * dict;
int count;
} CountDict;
static int
CountDict_init(CountDict *self, PyObject *args, PyObject *kwds)
{
self->dict = PyDict_New();
self->count = 0;
return 0;
}
static void
CountDict_dealloc(CountDict *self)
{
Py_XDECREF(self->dict);
self->ob_type->tp_free((PyObject*)self);
}
static PyObject *
CountDict_set(CountDict *self, PyObject *args)
{
const char *key;
PyObject *value;
if (!PyArg_ParseTuple(args, "sO:set", &key, &value)) {
return NULL;
}
if (PyDict_SetItemString(self->dict, key, value) < 0) {
return NULL;
}
self->count++;
return Py_BuildValue("i", self->count);
}
static PyMemberDef
CountDict_members[] = {
{ "dict", T_OBJECT, offsetof(CountDict, dict), 0,
"The dictionary of values collected so far." },
{ "count", T_INT, offsetof(CountDict, count), 0,
"The number of times set() has been called." },
{ NULL }
};
static PyMethodDef
CountDict_methods[] = {
{ "set", (PyCFunction) CountDict_set, METH_VARARGS,
"Set a key and increment the count." },
// typically there would be more here...
{ NULL }
};
static PyTypeObject
CountDictType = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"CountDict", /* tp_name */
sizeof(CountDict), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)CountDict_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags*/
"CountDict object", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
CountDict_methods, /* tp_methods */
CountDict_members, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)CountDict_init, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
};
// Module definition
static PyModuleDef
moduledef = {
PyModuleDef_HEAD_INIT,
"countdict",
MODULE_DOC,
-1,
NULL, /* methods */
NULL,
NULL, /* traverse */
NULL, /* clear */
NULL
};
PyObject *
PyInit_countdict(void)
{
PyObject * mod = PyModule_Create(&moduledef);
if (mod == NULL) {
return NULL;
}
CountDictType.tp_new = PyType_GenericNew;
if (PyType_Ready(&CountDictType) < 0) {
Py_DECREF(mod);
return NULL;
}
Py_INCREF(&CountDictType);
PyModule_AddObject(mod, "CountDict", (PyObject *)&CountDictType);
return mod;
}
他のヒント
あなたがすることはできません! Cは「クラス」を持っていない、それだけでstruct
sを持っています。そしてstruct
コード(メソッドまたは関数)を持つことができません。
あなたが、しかし、関数ポインタと偽それをます:
/* struct object has 1 member, namely a pointer to a function */
struct object {
int (*class)(void);
};
/* create a variable of type `struct object` and call it `new` */
struct object new;
/* make its `class` member point to the `rand()` function */
new.class = rand;
/* now call the "object method" */
new.class();
サンプルソースコードから始めることをお勧めします ここ -- これは Python 3 のソースの一部であり、特に必要なこと (およびその他のこと) を実行する方法を例によって示すために存在します -- C API を使用してモジュールを作成し、新しい型を作成しますそのモジュールには、その型にメソッドと属性が与えられます。これは基本的にソースの最初の部分であり、最終的には次の定義になります。 Xxo_Type
-- 次に、さまざまな種類の関数、その他のあまり気にしないタイプの定義方法の例が表示され、最後に適切なモジュール オブジェクトとその初期化が表示されます (もちろん、そのほとんどはスキップできますが、モジュール オブジェクトと対象の型の定義につながる初期化の部分;-)。
そのソースを研究し、特定のニーズに合わせて調整する際に生じる可能性のある質問のほとんどには、適切な答えが含まれています。 ドキュメント, 、特に セクション 「オブジェクト実装サポート」 -- もちろん、いつでもここで新しい質問を開くことができます (問題ごとに 1 つが最適です -- 実際の多くの質問を含む「質問」) 質問 これはいつも面倒です!-) 自分が何をしているのか、その結果として何を期待していたのか、そしてその代わりに何が表示されているのかを正確に示すこと -- そうすれば、かなり役立つものが含まれる傾向にある答えが得られます;-)。