Python C API:使用 Py_LIMITED_API 子类化(内置)类型
Python C API: Subclassing (builtin) types with Py_LIMITED_API
我正在尝试移植现有的 C Python 扩展以使用 Py_LIMITED_API
,这样我们就不必为我们支持的所有 python 版本构建扩展.
我面临的一个问题是,这个库提供了一个子类 python float
类型的类型。
最后的带有示例的官方文档 (https://docs.python.org/3.5/extending/newtypes.html#subclassing-other-types) 没有提到有限的 API,我面临的问题是 PyFloatObject
不是稳定 ABI 的一部分,这将是创建基本结构所必需的:
typedef struct {
PyFloatObject base;
int state;
} SubclassedFloat;
有没有办法在使用 Py_LIMITED_API
时对内置类型进行子类化,尤其是 float
,或者这是不可能的?
在 Python c-extensions discord 上回答了这个问题:
https://discord.com/channels/267624335836053506/728390945384431688/981133468652154920
基本上,您必须在运行时从 PyFloat_Type
获取 __basicsize__
类型属性以声明您的对象大小:
//Code simplified for brevity
struct SubclassedFloatObject
{
// put your data members here
};
Py_ssize_t PyFloat_basicsize = PyLong_AsSsize_t(
PyObject_GetAttrString(
(PyObject*)&PyFloat_Type,
"__basicsize__"));
PyType_Spec SubclassedFloat_spec = {
"SubclassedFloat", //name
static_cast<int>(PyFloat_basicsize + sizeof(SubclassedFloatObject)), //basicsize
0, //itemsize
Py_TPFLAGS_DEFAULT, //flags
SubclassedFloat_slots //slots; /* terminated by slot==0. */
};
每当您访问您的对象时,您都必须为此大小偏移 PyObject*
指针:
int SomePythonFunc(PyObject* self)
{
SubclassedFloat* p_data = (SubclassedFloat*)((uintptr_t)(self) + PyFloat_basicsize);
// do something with p_data
}
我正在尝试移植现有的 C Python 扩展以使用 Py_LIMITED_API
,这样我们就不必为我们支持的所有 python 版本构建扩展.
我面临的一个问题是,这个库提供了一个子类 python float
类型的类型。
最后的带有示例的官方文档 (https://docs.python.org/3.5/extending/newtypes.html#subclassing-other-types) 没有提到有限的 API,我面临的问题是 PyFloatObject
不是稳定 ABI 的一部分,这将是创建基本结构所必需的:
typedef struct {
PyFloatObject base;
int state;
} SubclassedFloat;
有没有办法在使用 Py_LIMITED_API
时对内置类型进行子类化,尤其是 float
,或者这是不可能的?
在 Python c-extensions discord 上回答了这个问题: https://discord.com/channels/267624335836053506/728390945384431688/981133468652154920
基本上,您必须在运行时从 PyFloat_Type
获取 __basicsize__
类型属性以声明您的对象大小:
//Code simplified for brevity
struct SubclassedFloatObject
{
// put your data members here
};
Py_ssize_t PyFloat_basicsize = PyLong_AsSsize_t(
PyObject_GetAttrString(
(PyObject*)&PyFloat_Type,
"__basicsize__"));
PyType_Spec SubclassedFloat_spec = {
"SubclassedFloat", //name
static_cast<int>(PyFloat_basicsize + sizeof(SubclassedFloatObject)), //basicsize
0, //itemsize
Py_TPFLAGS_DEFAULT, //flags
SubclassedFloat_slots //slots; /* terminated by slot==0. */
};
每当您访问您的对象时,您都必须为此大小偏移 PyObject*
指针:
int SomePythonFunc(PyObject* self)
{
SubclassedFloat* p_data = (SubclassedFloat*)((uintptr_t)(self) + PyFloat_basicsize);
// do something with p_data
}