我想用Py_LIMITED_API美元.因此,我没有静态地定义我的Python类型,而是动态地定义它,规范和槽如下所示.

struct MyType { PyObject_HEAD };

static void MyType_dealloc( MyType * self ) { PyObject_DEL( self ); }

static PyObject * MyType_new( PyTypeObject * type, PyObject * args, PyObject * kwds ) {
    return (PyObject *)PyObject_NEW( MyType, type );
}

static int MyType_init( MyType * self, PyObject * args, PyObject * kwds ) { return 0; }

static PyType_Slot MyType_slots[] = {
    { Py_tp_doc, (void *)PyDoc_STR("MyType objects") },
    { Py_tp_dealloc, (void *)&MyType_dealloc },
    { Py_tp_init, (void *)&MyType_init },
    { Py_tp_new, (void *)&MyType_new },
    { 0, NULL }
};

static PyType_Spec MyType_spec = {
    "MyType",
    sizeof(MyType),
    0,
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
    MyType_slots
};

static PyTypeObject * MyTypePtr = NULL;

static PyModuleDef MyModule = {
    PyModuleDef_HEAD_INIT,
    "MyModule",
    "My C++ Module.",
    -1,
    NULL, NULL, NULL, NULL, NULL
};

PyMODINIT_FUNC
PyInit_MyModule(void)
{
    PyObject* m = PyModule_Create( &MyModule );
    if (m == NULL) return NULL;
    MyTypePtr = (PyTypeObject*)PyType_FromSpec( &MyType_spec );
    if ( MyTypePtr == NULL ) return NULL;
    if ( PyType_Ready( MyTypePtr ) < 0 ) return NULL;
    PyDict_SetItemString( MyTypePtr->tp_dict, "Normal", PyLong_FromLong( 0 ) );
    PyDict_SetItemString( MyTypePtr->tp_dict, "Custom", PyLong_FromLong( 15 ) );
    Py_INCREF( MyTypePtr );
    PyModule_AddObject( m, "MyType", (PyObject *)MyTypePtr );
    return m;
}

使用我的模块的这个定义,我可以编写以下代码.

from MyModule import *
print( MyType.Normal )
print( MyType.Custom )

我的问题是,对于Py_LIMITED_API,我不能使用tp_dict来定义常量值NormalCustom.

我试着用PyType_GetSlot,但Py_tp_dict不存在.(我想我理解原因:这是因为它允许修改现有类型.)

现在我的问题是:在上面带有规格和槽的代码中,我如何定义类型MyType的常量NormalCustom而不使用tp_dict

推荐答案

有一个非常简单的答案:在类型对象上调用PyObject_SetAttrString.

PyMODINIT_FUNC
PyInit_MyModule(void)
{
    PyObject* m = PyModule_Create( &MyModule );
    if (m == NULL) return NULL;
    MyTypePtr = (PyTypeObject*)PyType_FromSpec( &MyType_spec );
    if ( MyTypePtr == NULL ) return NULL;
    if ( PyType_Ready( MyTypePtr ) < 0 ) return NULL;
    PyObject_SetAttrString( (PyObject*)MyTypePtr, "Normal", PyLong_FromLong( 0 ) );
    PyObject_SetAttrString( (PyObject*)MyTypePtr, "Custom", PyLong_FromLong( 15 ) );
    Py_INCREF( MyTypePtr );
    PyModule_AddObject( m, "MyType", (PyObject *)MyTypePtr );
    return m;
}

我猜它也适用于PyObject_SetAttr.

不再使用tp_dict.

可以用这个激活Py_LIMITED_API个.

Python相关问答推荐

通过交换 node 对链接列表进行 Select 排序

Python中是否有方法从公共域检索搜索结果

Python中的嵌套Ruby哈希

pandas滚动和窗口中有效观察的最大数量

Polars:用氨纶的其他部分替换氨纶的部分

如何在Python中找到线性依赖mod 2

当我try 在django中更新模型时,模型表单数据不可见

在单个对象中解析多个Python数据帧

Django—cte给出:QuerySet对象没有属性with_cte''''

* 动态地 * 修饰Python中的递归函数

如何创建引用列表并分配值的Systemrame列

Python 3试图访问在线程调用中实例化的类的对象

使用类型提示进行类型转换

获取PANDA GROUP BY转换中的组的名称

仅使用预先计算的排序获取排序元素

合并相似列表

Django在一个不是ForeignKey的字段上加入'

用来自另一个数据框的列特定标量划分Polars数据框中的每一列,

为什么Visual Studio Code说我的代码在使用Pandas concat函数后无法访问?

如何在Python中创建仅包含完整天数的月份的列表