gpt4 book ai didi

Python C-API 使 len(...) 与扩展类一起工作

转载 作者:太空狗 更新时间:2023-10-30 02:35:35 28 4
gpt4 key购买 nike

在 Python 中创建类时,我可以简单地创建一个 def __len__(self): 方法来使 len(InstanceOfMyClass) 工作,但是我做不到了解如何通过 C-API 使用扩展类执行此操作。

我尝试添加一个 __len__ 方法,但这似乎不起作用

{"__len__",(PyCFunction)&TestClass_GetLen,METH_NOARGS,""},

Python测试代码:

def test(my_instance):
x = len(my_instance)#exception
return x

TypeError: object of type 'test_module.test_class' has no len()

测试类代码

struct TestClass;
static int TestClass_Init(TestClass *self, PyObject *args, PyObject* kwds);
static void TestClass_Dealloc(TestClass *self);
static PyObject* TestClass_GetLen(TestClass *self);

struct TestClass
{
PyObject_HEAD;
};
static PyMethodDef TestClass_methods[] =
{
{"__len__",(PyCFunction)&TestClass_GetLen,METH_O,""},
{NULL}
};
static PyTypeObject TestClass_type = {PyObject_HEAD_INIT(NULL)};
bool InitTestClass(PyObject *module)
{
TestClass_type.tp_basicsize = sizeof(TestClass);
TestClass_type.tp_name = PY_MODULE_NAME".TestClass";
TestClass_type.tp_doc = "";
TestClass_type.tp_flags = Py_TPFLAGS_DEFAULT;
TestClass_type.tp_methods = TestClass_methods;
TestClass_type.tp_new = PyType_GenericNew;
TestClass_type.tp_init = (initproc)TestClass_Init;
TestClass_type.tp_dealloc = (destructor)TestClass_Dealloc;
if(PyType_Ready(TestClass_type) < 0) return false;

Py_INCREF(TestClass_type);
PyModule_AddObject(module, "TestClass", (PyObject*)&TestClass_type);
return true;
};
void TestClass_Dealloc(TestClass *self)
{
Py_TYPE(self)->tp_free((PyObject*)self);
}
int TestClass_Init(TestClass *self, PyObject *args, PyObject* kwds)
{
return 0;
}
PyObject* TestClass_GetLen(TestClass *self)
{
return PyLong_FromLong(55);
}

最佳答案

正如 Igniacio 所说,正确的方法是填充类型对象的 tp_as_sequence 成员。这是一个最小的例子:

#include <Python.h>

/**
* C structure and methods definitions
*/

typedef struct {
PyObject_HEAD;
} TestObject;

static Py_ssize_t
TestClass_len(TestObject* self)
{
return 55;
}

/**
* Python definitions
*/

static PySequenceMethods TestClass_sequence_methods = {
TestClass_len, /* sq_length */
};

static PyTypeObject TestClass = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"testmodule.TestClass", /*tp_name*/
sizeof(TestObject), /*tp_basicsize*/
};

/**
* Module entry point
*/
#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
#define PyMODINIT_FUNC void
#endif
PyMODINIT_FUNC
inittestmodule(void)
{
PyObject* m;

TestClass.tp_new = PyType_GenericNew;
TestClass.tp_as_sequence = &TestClass_sequence_methods;
TestClass.tp_flags = Py_TPFLAGS_DEFAULT;

if (PyType_Ready(&TestClass) < 0)
return;

m = Py_InitModule3("testmodule", NULL, "");

Py_INCREF(&TestClass);
PyModule_AddObject(m, "TestClass", (PyObject *)&TestClass);
}

另一种(更复杂和更慢)的方法是使用 PyCFunction_NewPyMethod_New 在模块的 init 函数中动态地向您的类添加一个 __len__ 方法> 和 PyObject_SetAttr。这看起来更像是您粘贴的代码,只是您在 C 方法表中定义了 __len__,这是行不通的。

关于Python C-API 使 len(...) 与扩展类一起工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2064276/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com