1- // gh-91321: Very basic C++ test extension to check that the Python C API is
1+ // gh-91321: Basic C++ test extension to check that the Python C API is
22// compatible with C++ and does not emit C++ compiler warnings.
33//
44// The code is only built, not executed.
@@ -159,6 +159,8 @@ test_unicode(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
159159 Py_RETURN_NONE;
160160}
161161
162+ // VirtualPyObject is incompatible with opaque PyObject
163+ #ifndef Py_TARGET_ABI3T
162164/* Test a `new`-allocated object with a virtual method.
163165 * (https://github.com/python/cpython/issues/94731) */
164166
@@ -237,6 +239,8 @@ test_virtual_object(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
237239 }
238240 Py_RETURN_NONE;
239241}
242+ #endif // Py_TARGET_ABI3T
243+
240244
241245static PyObject *
242246test_datetime (PyObject *Py_UNUSED (module ), PyObject *Py_UNUSED(args))
@@ -256,7 +260,9 @@ static PyMethodDef _testcppext_methods[] = {
256260 {" add" , _testcppext_add, METH_VARARGS , _testcppext_add_doc},
257261 {" test_api_casts" , test_api_casts, METH_NOARGS , _Py_NULL},
258262 {" test_unicode" , test_unicode, METH_NOARGS , _Py_NULL},
263+ #ifndef Py_TARGET_ABI3T
259264 {" test_virtual_object" , test_virtual_object, METH_NOARGS , _Py_NULL},
265+ #endif
260266 {" test_datetime" , test_datetime, METH_NOARGS , _Py_NULL},
261267 // Note: _testcppext_exec currently runs all test functions directly.
262268 // When adding a new one, add a call there.
@@ -282,9 +288,11 @@ _testcppext_exec(PyObject *module)
282288 if (!result) return -1 ;
283289 Py_DECREF (result);
284290
291+ #ifndef Py_TARGET_ABI3T
285292 result = PyObject_CallMethod (module , " test_virtual_object" , " " );
286293 if (!result) return -1 ;
287294 Py_DECREF (result);
295+ #endif
288296
289297 result = PyObject_CallMethod (module , " test_datetime" , " " );
290298 if (!result) return -1 ;
@@ -313,40 +321,40 @@ _testcppext_exec(PyObject *module)
313321 return 0 ;
314322}
315323
316- // Need to ignore "-Wpedantic" warnings; see VirtualPyObject_Slots above
317- _Py_COMP_DIAG_PUSH
318- #if defined(__GNUC__)
319- #pragma GCC diagnostic ignored "-Wpedantic"
320- #elif defined(__clang__)
321- #pragma clang diagnostic ignored "-Wpedantic"
322- #endif
323324
324- static PyModuleDef_Slot _testcppext_slots[] = {
325- {Py_mod_exec, reinterpret_cast <void *>(_testcppext_exec)},
326- {0 , _Py_NULL}
325+ PyDoc_STRVAR (_testcppext_doc, " C++ test extension." );
326+ PyABIInfo_VAR (abi_info);
327+
328+ static PySlot _testcppext_slots[] = {
329+ PySlot_PTR_STATIC (Py_mod_abi, &abi_info),
330+ PySlot_PTR_STATIC (Py_mod_name, (void *)STR (MODULE_NAME )),
331+ PySlot_PTR_STATIC (Py_mod_doc, (void *)(char *)_testcppext_doc),
332+ PySlot_PTR_STATIC (Py_mod_exec, (void *)_testcppext_exec),
333+ PySlot_PTR_STATIC (Py_mod_methods, _testcppext_methods),
334+ PySlot_PTR_STATIC (Py_mod_gil, Py_MOD_GIL_NOT_USED),
335+ PySlot_END,
327336};
328337
329- _Py_COMP_DIAG_POP
330338
331- PyDoc_STRVAR (_testcppext_doc, " C++ test extension." );
339+ #define _FUNC_NAME (NAME ) PyModExport_ ## NAME
340+ #define FUNC_NAME (NAME ) _FUNC_NAME(NAME )
332341
333- static struct PyModuleDef _testcppext_module = {
334- PyModuleDef_HEAD_INIT, // m_base
335- STR (MODULE_NAME ), // m_name
336- _testcppext_doc, // m_doc
337- 0 , // m_size
338- _testcppext_methods, // m_methods
339- _testcppext_slots, // m_slots
340- _Py_NULL, // m_traverse
341- _Py_NULL, // m_clear
342- _Py_NULL, // m_free
343- };
342+ PyMODEXPORT_FUNC
343+ FUNC_NAME (MODULE_NAME )(void )
344+ {
345+ return _testcppext_slots;
346+ }
344347
345- #define _FUNC_NAME (NAME ) PyInit_ ## NAME
346- #define FUNC_NAME (NAME ) _FUNC_NAME(NAME )
348+ // Also define the soft-deprecated entrypoint to ensure it isn't called
349+
350+ #define _INITFUNC_NAME (NAME ) PyInit_ ## NAME
351+ #define INITFUNC_NAME (NAME ) _INITFUNC_NAME(NAME )
347352
348353PyMODINIT_FUNC
349- FUNC_NAME (MODULE_NAME )(void )
354+ INITFUNC_NAME (MODULE_NAME )(void )
350355{
351- return PyModuleDef_Init (&_testcppext_module);
356+ PyErr_SetString (
357+ PyExc_AssertionError,
358+ " PyInit_* function called while a PyModExport_* one is available" );
359+ return NULL ;
352360}
0 commit comments