@@ -204,59 +204,26 @@ value must be in a particular range or must satisfy other conditions,
204204:c:data: `PyExc_ValueError ` is appropriate.
205205
206206You can also define a new exception that is unique to your module. For this, you
207- usually declare an object variable in the module's state and initialize it
208- in the module's :c:data: `Py_mod_exec ` function (:c:func: `!spam_module_exec `)
209- with an exception object::
210-
211- typedef struct {
212- PyObject *SpamError;
213- } spam_state;
207+ usually declare a static object variable at the beginning of your file::
214208
215- static int
216- spam_module_exec(PyObject *module)
217- {
218- spam_state *state = PyModule_GetState(module);
219- if (state == NULL) {
220- return -1;
221- }
209+ static PyObject *SpamError;
222210
223- state->SpamError = PyErr_NewException("spam.error", NULL, NULL);
224- if (state->SpamError == NULL) {
225- return -1;
226- }
227- if (PyModule_AddObjectRef(module, "SpamError", state->SpamError) < 0) {
228- return -1; // followed by spam_module_free() then Py_CLEAR()
229- }
211+ and initialize it in the module's :c:data: `Py_mod_exec ` function
212+ (:c:func: `!spam_module_exec `)
230213
231- return 0;
232- }
214+ with an exception object::
233215
234216 static int
235- spam_module_traverse(PyObject *module, visitproc visit, void *arg) {
236- spam_state *state = PyModule_GetState(module);
237- if (state == NULL) {
217+ spam_module_exec(PyObject *m)
218+ {
219+ SpamError = PyErr_NewException("spam.error", NULL, NULL);
220+ if (PyModule_AddObjectRef(m, "error", SpamError) < 0) {
238221 return -1;
239222 }
240- Py_VISIT(st->SpamError);
241- return 0;
242- }
243223
244- static int
245- spam_module_clear(PyObject *module) {
246- spam_state *state = PyModule_GetState(module);
247- if (state == NULL) {
248- return -1;
249- }
250- Py_CLEAR(st->SpamError);
251224 return 0;
252225 }
253226
254- static void
255- spam_module_free(void *module)
256- {
257- (void)spam_module_clear((PyObject *)module);
258- }
259-
260227 static PyModuleDef_Slot spam_module_slots[] = {
261228 {Py_mod_exec, spam_module_exec},
262229 {0, NULL}
@@ -265,11 +232,8 @@ with an exception object::
265232 static struct PyModuleDef spam_module = {
266233 .m_base = PyModuleDef_HEAD_INIT,
267234 .m_name = "spam",
268- .m_size = sizeof(spam_state) , // size of per-module state
235+ .m_size = 0 , // non-negative
269236 .m_slots = spam_module_slots,
270- .m_traverse = spam_module_traverse,
271- .m_clear = spam_module_clear,
272- .m_free = spam_module_free,
273237 };
274238
275239 PyMODINIT_FUNC
@@ -306,10 +270,7 @@ call to :c:func:`PyErr_SetString` as shown below::
306270 return NULL;
307271 sts = system(command);
308272 if (sts < 0) {
309- spam_state *state = PyModule_GetState(self);
310- if (state != NULL) {
311- PyErr_SetString(state->SpamError, "System command failed");
312- }
273+ PyErr_SetString(SpamError, "System command failed");
313274 return NULL;
314275 }
315276 return PyLong_FromLong(sts);
@@ -1297,25 +1258,19 @@ The ``#define`` is used to tell the header file that it is being included in the
12971258exporting module, not a client module. Finally, the module's initialization
12981259function must take care of initializing the C API pointer array::
12991260
1300- typedef struct {
1301- void *PySpam_API[PySpam_API_pointers];
1302- } spam_state;
1303-
13041261 static int
1305- spam_module_exec(PyObject *module )
1262+ spam_module_exec(PyObject *m )
13061263 {
1307- spam_state *state = PyModule_GetState(module);
1308- if (state == NULL) {
1309- return -1;
1310- }
1264+ static void *PySpam_API[PySpam_API_pointers];
1265+ PyObject *c_api_object;
13111266
13121267 /* Initialize the C API pointer array */
1313- state-> PySpam_API[PySpam_System_NUM] = PySpam_System;
1268+ PySpam_API[PySpam_System_NUM] = (void *) PySpam_System;
13141269
13151270 /* Create a Capsule containing the API pointer array's address */
1316- PyObject *capi = PyCapsule_New(state-> PySpam_API, "spam._C_API", NULL);
1317- if (PyModule_Add(module, "_C_API", capi) < 0) {
1318- Py_CLEAR(capi);
1271+ c_api_object = PyCapsule_New((void *) PySpam_API, "spam._C_API", NULL);
1272+
1273+ if (PyModule_Add(m, "_C_API", c_api_object) < 0) {
13191274 return -1;
13201275 }
13211276
@@ -1330,7 +1285,7 @@ function must take care of initializing the C API pointer array::
13301285 static struct PyModuleDef spam_module = {
13311286 .m_base = PyModuleDef_HEAD_INIT,
13321287 .m_name = "spam",
1333- .m_size = sizeof(spam_state) ,
1288+ .m_size = 0 ,
13341289 .m_slots = spam_module_slots,
13351290 };
13361291
@@ -1340,6 +1295,9 @@ function must take care of initializing the C API pointer array::
13401295 return PyModuleDef_Init(&spam_module);
13411296 }
13421297
1298+ Note that ``PySpam_API `` is declared ``static ``; otherwise the pointer
1299+ array would disappear when :c:func: `!PyInit_spam ` terminates!
1300+
13431301The bulk of the work is in the header file :file: `spammodule.h `, which looks
13441302like this::
13451303
@@ -1368,9 +1326,21 @@ like this::
13681326 #else
13691327 /* This section is used in modules that use spammodule's API */
13701328
1329+ static void **PySpam_API;
1330+
13711331 #define PySpam_System \
13721332 (*(PySpam_System_RETURN (*)PySpam_System_PROTO) PySpam_API[PySpam_System_NUM])
13731333
1334+ /* Return -1 on error, 0 on success.
1335+ * PyCapsule_Import will set an exception if there's an error.
1336+ */
1337+ static int
1338+ import_spam(void)
1339+ {
1340+ PySpam_API = (void **)PyCapsule_Import("spam._C_API", 0);
1341+ return (PySpam_API != NULL) ? 0 : -1;
1342+ }
1343+
13741344 #endif
13751345
13761346 #ifdef __cplusplus
@@ -1379,22 +1349,15 @@ like this::
13791349
13801350 #endif /* !defined(Py_SPAMMODULE_H) */
13811351
1382-
1383- typedef struct {
1384- void **PySpam_API;
1385- } client_state;
1352+ All that a client module must do in order to have access to the function
1353+ :c:func: `!PySpam_System ` is to call the function (or rather macro)
1354+ :c:func: `!import_spam ` in its initialization function::
13861355
13871356 static int
1388- client_module_exec(PyObject *module )
1357+ client_module_exec(PyObject *m )
13891358 {
1390- client_state *state = PyModule_GetState(module);
1391- if (state == NULL) {
1359+ if (import_spam() < 0)
13921360 return -1;
1393- }
1394- state->PySpam_API = (void **)PyCapsule_Import("spam._C_API", 0);
1395- if (state->PySpam_API == NULL) {
1396- return -1;
1397- }
13981361 /* additional initialization can happen here */
13991362 return 0;
14001363 }
@@ -1407,7 +1370,7 @@ like this::
14071370 static struct PyModuleDef client_module = {
14081371 .m_base = PyModuleDef_HEAD_INIT,
14091372 .m_name = "client",
1410- .m_size = sizeof(client_state) ,
1373+ .m_size = 0 ,
14111374 .m_slots = client_module_slots,
14121375 };
14131376
0 commit comments