如何使用Py_LIMITED_API定义C++扩展中定义的 Python 类型的常量值?

How to define constant values of Python types defined in C++ extension with Py_LIMITED_API?

提问人:Didier Trosset 提问时间:11/6/2023 更新时间:11/9/2023 访问量:50

问:

我想使用 .因此,我不是静态地定义我的 Python 类型,而是动态地定义它,其规格和插槽如下所示。Py_LIMITED_API

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_APItp_dictNormalCustom

我尝试使用 ,但不存在。(我想我明白为什么:这是因为它允许修改现有类型。PyType_GetSlotPy_tp_dict

现在我的问题是:在上面带有规范和插槽的代码中,如何在不使用的情况下定义常量和类型?NormalCustomMyTypetp_dict

C++ C 蟒蛇 C-API

评论

0赞 Didier Trosset 11/6/2023
@AbdulNiyasPM 谢谢,但旨在定义模块的常量值。我想将常量值分配给类型。PyModule_AddIntConstantMyType

答:

1赞 Didier Trosset 11/9/2023 #1

有一个非常简单的答案:调用类型对象。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