@@ -149,7 +149,7 @@ Including the Header
149149
150150
151151Now, put the first line in the file: include :file: `Python.h ` to pull in
152- all definitions of the Python C API:
152+ all declarations of the Python C API:
153153
154154.. literalinclude :: ../includes/capi-extension/spammodule-01.c
155155 :start-at: <Python.h>
@@ -158,8 +158,8 @@ all definitions of the Python C API:
158158This header contains all of the Python C API.
159159
160160Next, bring in the declaration of the C library function we want to call.
161- Documentation of the :c:func: `system ` function tells us that we need
162- `` stdlib.h `` :
161+ Documentation of the :c:func: `system ` function tells us that teh necessary
162+ header is :
163163
164164.. literalinclude :: ../includes/capi-extension/spammodule-01.c
165165 :start-at: <stdlib.h>
@@ -177,6 +177,181 @@ which affect the standard headers on some systems.
177177 and ``stdlib `` is one of them.
178178 However, it is good practice to explicitly include what you need.
179179
180+ With the includes in place, compile and import the extension again.
181+ You should get the same exception as with the empty file.
182+
183+ .. note ::
184+
185+ Third-party build tools should handle pointing the compiler to
186+ the CPython headers and libraries, and setting appropriate options.
187+
188+ If you are running the compiler directly, you will need to do this yourself.
189+ If your installation of Python comes with a corresponding ``python-config ``
190+ command, you can run something like:
191+
192+ .. code-block :: shell
193+
194+ gcc --shared $( python-config --cflags --ldflags) spammodule.c -o spam.so
195+
196+
197+ Module export hook
198+ ==================
199+
200+ The exception you should be getting tells you that Python is looking for an
201+ module :ref: `export hook <extension-export-hook >` function.
202+ Let's define one.
203+
204+ First, let's add a prototype:
205+
206+ .. literalinclude :: ../includes/capi-extension/spammodule-01.c
207+ :start-after: /// Export hook prototype
208+ :end-before: ///
209+
210+ The :c:macro: `PyMODEXPORT_FUNC ` macro declares the function's
211+ return type, and adds any special linkage declarations required by the platform
212+ to make the compiled extension export the function.
213+ For C++, it declares the function as ``extern "C" ``.
214+
215+ .. tip ::
216+ The prototype is not strictly necessary, but some modern C compilers emit
217+ warnings when a public, exported function has no prototype declaration.
218+ It's better to add a prototype than disable the warning, so that in other
219+ code you're notified in common cases of forgetting a header or misspelling
220+ a name.
221+
222+ After the prototype, add the function itself.
223+ For now, make it return ``NULL ``:
224+
225+ .. code-block :: c
226+
227+ PyMODEXPORT_FUNC
228+ PyModExport_spam(void)
229+ {
230+ return NULL;
231+ }
232+
233+ Compile and load the module again.
234+ You should get a different error this time:
235+
236+ .. code-block :: pycon
237+
238+ >>> import spam
239+ Traceback (most recent call last):
240+ File "<string>", line 1, in <module>
241+ import spam
242+ SystemError: module export hook for module 'spam' failed without setting an exception
243+
244+ Many functions in the Python C API, including export hooks, are expected to
245+ do two things to signal that they have failed: return ``NULL ``, and
246+ set an exception.
247+ Here, Python assumes that you only did half of this.
248+
249+ .. note ::
250+
251+ This is one of a few situation where CPython checks this situation and
252+ emits a "nice" error message.
253+ Elsewhere, returning ``NULL `` without setting an exception can
254+ trigger undefined behavior.
255+
256+
257+ The slot table
258+ ==============
259+
260+ Rather than ``NULL ``, the export hook should return the information needed to
261+ create a module, as a ``static `` array of :c:type: `PyModuleDef_Slot ` entries.
262+ Define this array just before your export hook:
263+
264+ .. code-block :: c
265+
266+ static PyModuleDef_Slot spam_slots[] = {
267+ {Py_mod_name, "spam"},
268+ {Py_mod_doc, PyDoc_STR("A wonderful module with an example function")},
269+ {0, NULL}
270+ };
271+
272+ The array contains:
273+
274+ * the module name (as a NUL-terminated UTF-8 encoded C string),
275+ * the docstring (similarly encoded), and
276+ * a zero-filled *sentinel * marking the end of the array.
277+
278+ .. tip ::
279+
280+ The :c:func: `PyDoc_STR ` macro can, in a special build mode, omit the
281+ docstring to save a bit of memory.
282+
283+ Return this array from your export hook, instead of ``NULL ``:
284+
285+ .. code-block :: c
286+ :emphasize-lines: 4
287+
288+ PyMODEXPORT_FUNC
289+ PyModExport_spam(void)
290+ {
291+ return spam_slots;
292+ }
293+
294+ Now, recompile and try it out:
295+
296+ .. code-block :: pycon
297+
298+ >>> import spam
299+ >>> print(spam)
300+ <module 'spam' from '/home/encukou/dev/cpython/spam.so'>
301+
302+ You now have a extension module!
303+ Try ``help(spam) `` to see the docstring.
304+
305+ The next step will be adding a function to it.
306+
307+
308+ Adding a function
309+ =================
310+
311+ To expose a C function to Python, you need three things:
312+
313+ * The *implementation *: a C function that does what you need, and
314+ * a *name * to use in Python code.
315+
316+ You can also add a *dosctring *.
317+ OK, *amongst * the things you need to expose a C function are
318+
319+
320+
321+
322+ The :c:type: `PyModuleDef_Slot ` array must be passed to the interpreter in the
323+ module's :ref: `export hook <extension-export-hook >` function.
324+ The hook must be named :c:func: `!PyModExport_name `, where *name * is the name
325+ of the module, and it should be the only non-\ ``static `` item defined in the
326+ module file.
327+
328+ Several modern C compilers emit warnings when you define a public function
329+ without a prototype declaration.
330+ Normally, prototypes go in a header file so they can be used from other
331+ C files.
332+ A function without a prototype is allowed in C, but is normally a strong
333+ hint that something is wrong -- for example, the name is misspelled.
334+
335+ In our case, Python will load our function dynamically, so a prototype
336+ isn't needed.
337+ We'll only add one to avoid well-meaning compiler warnings:
338+
339+ .. literalinclude :: ../includes/capi-extension/spammodule-01.c
340+ :start-after: /// Export hook prototype
341+ :end-before: ///
342+
343+ The :c:macro: `PyMODEXPORT_FUNC ` macro declares the function's
344+ ``PyModuleDef_Slot * `` return type, and adds any special linkage
345+ declarations required by the platform.
346+ For C++, it declares the function as ``extern "C" ``.
347+
348+ Just after the prototype, we'll add the function itself.
349+ Its only job is to return the slot array, which in turn contains
350+ all the information needed to create our module object:
351+
352+ .. literalinclude :: ../includes/capi-extension/spammodule-01.c
353+ :start-after: /// Module export hook
354+ :end-before: ///
180355
181356
182357The ``spam `` module
0 commit comments