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
}