短いバージョン: とPyType_Type
をPython 3で使用して、PyClass_New
の代わりに使用する場合は、辞書を作成する前にクラスを作成する必要があります。ただし、PyMethod_New
では、メソッドを作成する前にクラスを知っている必要があります。 Python 3の新しいクラスの辞書にメソッドを追加するにはどうすればよいですか?Python 3でC API経由で新しいクラスをメソッドで定義する方法は?
Python 2では、私はPyClass_New
で新しいクラスを定義するために使用されました。ここで私は方法hello
と新しいクラスexample.MyClass
を定義し、(パイソン2)最小限の実施例は、次のとおり
#include <Python.h>
#include <stdio.h>
PyObject *
callback(PyObject *obj, PyObject *args)
{
printf("Hello world!\n");
return Py_None;
}
int
main(int argc, char *argv[])
{
Py_SetProgramName(argv[0]);
Py_Initialize();
PyObject *module = PyModule_New("example");
PyDict_SetItemString(PyImport_GetModuleDict(), "example", module);
PyObject *dict = PyDict_New();
PyObject *classname = PyBytes_FromString("MyClass");
PyObject *class = PyClass_New(PyTuple_New(0), dict, classname);
PyMethodDef method_def;
method_def.ml_name = "method_closure";
method_def.ml_meth = callback;
method_def.ml_flags = 1;
method_def.ml_doc = "Method closure";
PyObject *closure = PyCFunction_New(&method_def, NULL);
PyObject *method = PyMethod_New(closure, NULL, class);
PyDict_SetItemString(dict, "hello", method);
PyModule_AddObject(module, "MyClass", class);
PyRun_SimpleString("from example import MyClass\nMyClass().hello()");
Py_Finalize();
return 0;
}
PyClass_New
はPythonの3 CのAPIから除去しました。 What is the PyClass_New equivalent in Python 3?
しかし、それは辞書PyObject_CallFunctionObjArgs
は、新しいクラスの作成中にコピーされ、最後の引数に取ることと思わ:確かに、私はPyObject_CallFunctionObjArgs
は、次の質問の答えには例えば、代替として使用することができることを読んでPyObject_CallFunctionObjArgs
を呼び出す前にdict
に設定されているフィールドは、クラスのインスタンスで使用できますが、呼び出し後に設定されたフィールドは使用できません。 これは、メソッドを作成する前にクラスを知っていなければならないため、クラスを作成する前にdict
にメソッドを追加する必要があるため、上記のようにPyMethod_New
を使用できなくなります。
この依存ループは、PyInstanceMethod_new
を使用することで解決できます。後者はクラスの参照を取らないためです。私はこうして次の作業例を得ました(Python 3の場合は、main
のコードを与え、プリアンブルとコールバックは最初の例と同じです)。
int
main(int argc, char *argv[])
{
wchar_t progname[FILENAME_MAX + 1];
mbstowcs(progname, argv[0], strlen(argv[0]) + 1);
Py_SetProgramName(progname);
Py_Initialize();
PyObject *module = PyModule_New("example");
PyDict_SetItemString(PyImport_GetModuleDict(), "example", module);
PyObject *dict = PyDict_New();
PyMethodDef method_def;
method_def.ml_name = "method_closure";
method_def.ml_meth = callback;
method_def.ml_flags = 1;
method_def.ml_doc = "Method closure";
PyObject *closure = PyCFunction_New(&method_def, NULL);
PyObject *method = PyInstanceMethod_New(closure);
PyDict_SetItemString(dict, "hello", method);
PyObject *classname = PyUnicode_FromString("MyClass");
PyObject *class = PyObject_CallFunctionObjArgs(
(PyObject *) &PyType_Type, classname, PyTuple_New(0), dict);
PyModule_AddObject(module, "MyClass", class);
PyRun_SimpleString("from example import MyClass\nMyClass().hello()");
Py_Finalize();
return 0;
}
しかし、私は私がPyMethod_new
を使用して、Pythonの2バージョンに近いソリューションを書くために達成することができるかどうかを疑問に思う:動的に新しいメソッドを追加するために、その作成後にクラスを変更することが可能ですが、私ドンそれをどうやって行うのか理解していない。