以前我使用C API创建了一些Python类。当我要使用Python 3+构建旧项目时,它会产生以下编译错误
PyClass_New was not declared in this scope Py_InitModule was not declared in this scope
等价物是什么?
PyObject *pClassDic = PyDict_New();
PyObject *pClassName = PyBytes_FromString("MyClass");
PyObject *pClass = PyClass_New(NULL, pClassDic, pClassName);
答案 0 :(得分:4)
如果你不想经历设置对象和输入结构的麻烦,你应该能够通过从C调用Python的type(name, bases, dict)
来创建一个新类:
PyObject *pClassName = PyBytes_FromString("MyClass");
PyObject *pClassBases = PyTuple_New(0); // An empty tuple for bases is equivalent to `(object,)`
PyObject *pClassDic = PyDict_New();
// pClass = type(pClassName, pClassBases, pClassDic)
PyObject *pClass = PyObject_CallFunctionObjArgs(PyType_Type, pClassName, pClassBases, pClassDic, NULL);
Py_CLEAR(pClassName);
Py_CLEAR(pClassBases);
Py_CLEAR(pClassDic);
答案 1 :(得分:1)
从'cpburnz'完成答案,这是一个创建类对象并添加方法的函数:
PyObject *createClassObject(const char *name, PyMethodDef methods[])
{
PyObject *pClassName = PyUnicode_FromString(name);
PyObject *pClassBases = PyTuple_New(0); // An empty tuple for bases is equivalent to `(object,)`
PyObject *pClassDic = PyDict_New();
PyMethodDef *def;
// add methods to class
for (def = methods; def->ml_name != NULL; def++)
{
printf(" add method %s\n", def->ml_name);
PyObject *func = PyCFunction_New(def, NULL);
PyObject *method = PyInstanceMethod_New(func);
PyDict_SetItemString(pClassDic, def->ml_name, method);
Py_DECREF(func);
Py_DECREF(method);
}
// pClass = type(pClassName, pClassBases, pClassDic)
PyObject *pClass = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, pClassName, pClassBases, pClassDic, NULL);
Py_DECREF(pClassName);
Py_DECREF(pClassBases);
Py_DECREF(pClassDic);
return pClass;
}
然后,您可以像这样使用它:
static PyMethodDef foo_Methods[] =
{
{ "__init__", fooInit, METH_VARARGS, "doc" },
{ "do_something", fooDoSomething, METH_VARARGS, "doc" },
{ 0, 0 },
};
PyObject * fooClass = createClassObject("fooClass", foo_Methods);
PyModule_AddObject(module, "foo", fooClass );
请求PyModule_AddObject使python代码可以看到“foo”类。
注意:正如'RomanK'所建议的那样,使用PyTypeObject是一个很好的(可能更好)替代方案。
编辑:我确认直接使用PyTypeObject更好更容易,填充结构并调用PyModule_AddObject()以使新类型可用于Python。它更灵活,提供更大的灵活性,这是官方的方式。正如Cilyan所提到的,这里解释了所有内容:https://docs.python.org/3.3/extending/newtypes.html?highlight=pytypeobject