我正在尝试移植一个现有的C Python扩展来使用Py_LIMITED_API
,这样我们就不必为我们支持的所有Python版本构建扩展。
我面临的一个问题是,这个库提供了pythonfloat
类型的子类。
最后一个带有示例的官方文档(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的不和中得到了回答: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
}