如何从 Python C 扩展访问子类的对象结构字段?
How to access object struct fields of subclasses from a Python C extension?
我正在编写一个 Python 包装外部 C 库的 C 扩展。在原始库中有结构(为了便于讨论,类型为 T
),所以我的扩展 class 看起来像这样:
typedef struct {
PyObject_HEAD
T *cdata;
} TWrapperBase;
我也时不时要查一下Python中的指针,所以暴露了一个只读字段_cdata
是一个cdata
指针作为unsigned long long
(是的,我知道它不是很便携,但现在超出了范围)。
然后,我希望能够在 Python 中添加更多方法,但我不能将它们附加到 C 中声明的 class 中,所以我 subclass 它并添加我的新方法:
class TWrapper(TWrapperBase):
...
现在,在我的 C 扩展代码中,我需要一种访问 cdata
字段的方法,这样我就可以将它传递给库函数。我知道 self
不会是 TWrapperBase
的实例,而是 TWrapper
(这个 Python 版本)。 正确的做法是什么?
static PyObject * doStuff(PyObject *self)
{
T *cdata_ptr;
// How to get a pointer to cdata?
//
// This looks very unsafe to me, do I have any guarantee of
// the subclass memory layout?
// 1. cdata_ptr = ((TWrapperBase*)self)->cdata
//
// This is probably safe, but it seems to be a bit of a hassle
// to query it with a string key
// 2. cdata_ptr = PyLong_AsVoidPtr(PyObject_GetAttrString(self, "_cdata"))
do_important_library_stuff(cdata_ptr);
Py_INCREF(self);
return self;
}
谢谢!
// This looks very unsafe to me, do I have any guarantee of
// the subclass memory layout?
// 1. cdata_ptr = ((TWrapperBase*)self)->cdata
是的,行得通。您可以查看 Python's built-in types 的所有实现,发现它们做的事情几乎相同,通常无需检查它们是否在子类实例上运行。
我正在编写一个 Python 包装外部 C 库的 C 扩展。在原始库中有结构(为了便于讨论,类型为 T
),所以我的扩展 class 看起来像这样:
typedef struct {
PyObject_HEAD
T *cdata;
} TWrapperBase;
我也时不时要查一下Python中的指针,所以暴露了一个只读字段_cdata
是一个cdata
指针作为unsigned long long
(是的,我知道它不是很便携,但现在超出了范围)。
然后,我希望能够在 Python 中添加更多方法,但我不能将它们附加到 C 中声明的 class 中,所以我 subclass 它并添加我的新方法:
class TWrapper(TWrapperBase):
...
现在,在我的 C 扩展代码中,我需要一种访问 cdata
字段的方法,这样我就可以将它传递给库函数。我知道 self
不会是 TWrapperBase
的实例,而是 TWrapper
(这个 Python 版本)。 正确的做法是什么?
static PyObject * doStuff(PyObject *self)
{
T *cdata_ptr;
// How to get a pointer to cdata?
//
// This looks very unsafe to me, do I have any guarantee of
// the subclass memory layout?
// 1. cdata_ptr = ((TWrapperBase*)self)->cdata
//
// This is probably safe, but it seems to be a bit of a hassle
// to query it with a string key
// 2. cdata_ptr = PyLong_AsVoidPtr(PyObject_GetAttrString(self, "_cdata"))
do_important_library_stuff(cdata_ptr);
Py_INCREF(self);
return self;
}
谢谢!
// This looks very unsafe to me, do I have any guarantee of
// the subclass memory layout?
// 1. cdata_ptr = ((TWrapperBase*)self)->cdata
是的,行得通。您可以查看 Python's built-in types 的所有实现,发现它们做的事情几乎相同,通常无需检查它们是否在子类实例上运行。