403Webshell
Server IP : 121.121.20.254  /  Your IP : 216.73.217.141
Web Server : Microsoft-IIS/10.0
System : Windows NT WEB-SERVER 10.0 build 20348 (Windows Server 2022) AMD64
User : IUSR ( 0)
PHP Version : 8.3.28
Disable Function : NONE
MySQL : ON  |  cURL : ON  |  WGET : OFF  |  Perl : OFF  |  Python : OFF  |  Sudo : OFF  |  Pkexec : OFF
Directory :  C:/Python315/Doc/html/extending/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : C:/Python315/Doc/html/extending/first-extension-module.html
<!DOCTYPE html>

<html lang="en" data-content_root="../">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<meta property="og:title" content="Your first C API extension module" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://docs.python.org/3/extending/first-extension-module.html" />
<meta property="og:site_name" content="Python documentation" />
<meta property="og:description" content="This tutorial will take you through creating a simple Python extension module written in C or C++. We will use the low-level Python C API directly. For easier ways to create extension modules, see ..." />
<meta property="og:image" content="_static/og-image.png" />
<meta property="og:image:alt" content="Python documentation" />
<meta name="description" content="This tutorial will take you through creating a simple Python extension module written in C or C++. We will use the low-level Python C API directly. For easier ways to create extension modules, see ..." />
<meta name="theme-color" content="#3776ab">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">

    <title>Your first C API extension module &#8212; Python 3.15.0rc1 documentation</title><meta name="viewport" content="width=device-width, initial-scale=1.0">
    
    <link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=b86133f3" />
    <link rel="stylesheet" type="text/css" href="../_static/classic.css?v=234b1a7c" />
    <link rel="stylesheet" type="text/css" href="../_static/pydoctheme.css?v=4365c8fe" />
    <link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css?v=0fc419ee" />
    
    <script src="../_static/documentation_options.js?v=791e38b1"></script>
    <script src="../_static/doctools.js?v=9bcbadda"></script>
    <script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
    
    <script src="../_static/sidebar.js"></script>
    
    <link rel="search" type="application/opensearchdescription+xml"
          title="Search within Python 3.15.0rc1 documentation"
          href="../_static/opensearch.xml"/>
    <link rel="author" title="About these documents" href="../about.html" />
    <link rel="index" title="Index" href="../genindex.html" />
    <link rel="search" title="Search" href="../search.html" />
    <link rel="copyright" title="Copyright" href="../copyright.html" />
    <link rel="next" title="Using the C API: Assorted topics" href="extending.html" />
    <link rel="prev" title="Extending and Embedding the Python Interpreter" href="index.html" />
    
      
      <link rel="canonical" href="https://docs.python.org/3/extending/first-extension-module.html">
      
    

    
    <style>
      @media only screen {
        table.full-width-table {
            width: 100%;
        }
      }
    </style>
<link rel="stylesheet" href="../_static/pydoctheme_dark.css" media="(prefers-color-scheme: dark)" id="pydoctheme_dark_css">
    <link rel="shortcut icon" type="image/png" href="../_static/py.svg">
            <script type="text/javascript" src="../_static/copybutton.js"></script>
            <script type="text/javascript" src="../_static/menu.js"></script>
            <script type="text/javascript" src="../_static/search-focus.js"></script>
            <script type="text/javascript" src="../_static/themetoggle.js"></script> 
            <script type="text/javascript" src="../_static/rtd_switcher.js"></script>
            <meta name="readthedocs-addons-api-version" content="1">

  </head>
<body>
<div class="mobile-nav">
    <input type="checkbox" id="menuToggler" class="toggler__input" aria-controls="navigation"
           aria-pressed="false" aria-expanded="false" role="button" aria-label="Menu">
    <nav class="nav-content" role="navigation">
        <label for="menuToggler" class="toggler__label">
            <span></span>
        </label>
        <span class="nav-items-wrapper">
            <a href="https://www.python.org/" class="nav-logo">
                <img src="../_static/py.svg" alt="Python logo">
            </a>
            <span class="version_switcher_placeholder"></span>
            <form role="search" class="search" action="../search.html" method="get">
                <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" class="search-icon">
                    <path fill-rule="nonzero" fill="currentColor" d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 001.48-5.34c-.47-2.78-2.79-5-5.59-5.34a6.505 6.505 0 00-7.27 7.27c.34 2.8 2.56 5.12 5.34 5.59a6.5 6.5 0 005.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path>
                </svg>
                <input placeholder="Quick search" aria-label="Quick search" type="search" name="q">
                <input type="submit" value="Go">
            </form>
        </span>
    </nav>
    <div class="menu-wrapper">
        <nav class="menu" role="navigation" aria-label="main navigation">
            <div class="language_switcher_placeholder"></div>
            
<label class="theme-selector-label">
    Theme
    <select class="theme-selector" oninput="activateTheme(this.value)">
        <option value="auto" selected>Auto</option>
        <option value="light">Light</option>
        <option value="dark">Dark</option>
    </select>
</label>
  <div>
    <h3><a href="../contents.html">Table of Contents</a></h3>
    <ul>
<li><a class="reference internal" href="#">Your first C API extension module</a><ul>
<li><a class="reference internal" href="#what-we-ll-do">What we’ll do</a></li>
<li><a class="reference internal" href="#start-with-the-headers">Start with the headers</a></li>
<li><a class="reference internal" href="#running-your-build-tool">Running your build tool</a></li>
<li><a class="reference internal" href="#module-export-hook">Module export hook</a></li>
<li><a class="reference internal" href="#the-slot-table">The slot table</a></li>
<li><a class="reference internal" href="#exposing-a-function">Exposing a function</a><ul>
<li><a class="reference internal" href="#method-definitions">Method definitions</a></li>
</ul>
</li>
<li><a class="reference internal" href="#returning-an-integer">Returning an integer</a></li>
<li><a class="reference internal" href="#accepting-a-string">Accepting a string</a></li>
<li><a class="reference internal" href="#the-result">The result</a></li>
<li><a class="reference internal" href="#appendix-other-build-tools">Appendix: Other build tools</a><ul>
<li><a class="reference internal" href="#workaround-for-missing-pyinit-function">Workaround for missing PyInit function</a></li>
<li><a class="reference internal" href="#compiling-directly">Compiling directly</a><ul>
<li><a class="reference internal" href="#linux">Linux</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>

  </div>
  <div>
    <h4>Previous topic</h4>
    <p class="topless"><a href="index.html"
                          title="previous chapter">Extending and Embedding the Python Interpreter</a></p>
  </div>
  <div>
    <h4>Next topic</h4>
    <p class="topless"><a href="extending.html"
                          title="next chapter">Using the C API: Assorted topics</a></p>
  </div>
  <script>
    document.addEventListener('DOMContentLoaded', () => {
        const title = document.querySelector('meta[property="og:title"]').content;
        const elements = document.querySelectorAll('.improvepage');
        const pageurl = window.location.href.split('?')[0];
        elements.forEach(element => {
            const url = new URL(element.href.split('?')[0].replace("-nojs", ""));
            url.searchParams.set('pagetitle', title);
            url.searchParams.set('pageurl', pageurl);
            url.searchParams.set('pagesource', "extending/first-extension-module.rst");
            element.href = url.toString();
        });
    });
  </script>
  <div role="note" aria-label="source link">
    <h3>This page</h3>
    <ul class="this-page-menu">
      <li><a href="../bugs.html">Report a bug</a></li>
      <li><a class="improvepage" href="../improve-page-nojs.html">Improve this page</a></li>
      <li>
        <a href="https://github.com/python/cpython/blob/main/Doc/extending/first-extension-module.rst?plain=1"
            rel="nofollow">Show source
        </a>
      </li>
      
    </ul>
  </div>
        </nav>
    </div>
</div>

  
    <div class="related" role="navigation" aria-label="Related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="right" >
          <a href="../py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li class="right" >
          <a href="extending.html" title="Using the C API: Assorted topics"
             accesskey="N">next</a> |</li>
        <li class="right" >
          <a href="index.html" title="Extending and Embedding the Python Interpreter"
             accesskey="P">previous</a> |</li>

          <li><img src="../_static/py.svg" alt="Python logo" style="vertical-align: middle; margin-top: -1px"></li>
          <li><a href="https://www.python.org/">Python</a> &#187;</li>
          <li class="switchers">
            <div class="language_switcher_placeholder"></div>
            <div class="version_switcher_placeholder"></div>
          </li>
          <li>
              
          </li>
    <li id="cpython-language-and-version">
      <a href="../index.html">3.15.0rc1 Documentation</a> &#187;
    </li>

          <li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Extending and Embedding the Python Interpreter</a> &#187;</li>
        <li class="nav-item nav-item-this"><a href="">Your first C API extension module</a></li>
                <li class="right">
                    

    <div class="inline-search" role="search">
        <form class="inline-search" action="../search.html" method="get">
          <input placeholder="Quick search" aria-label="Quick search" type="search" name="q" id="search-box">
          <input type="submit" value="Go">
        </form>
    </div>
                     |
                </li>
            <li class="right">
<label class="theme-selector-label">
    Theme
    <select class="theme-selector" oninput="activateTheme(this.value)">
        <option value="auto" selected>Auto</option>
        <option value="light">Light</option>
        <option value="dark">Dark</option>
    </select>
</label> |</li>
            
      </ul>
    </div>    

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body" role="main">
            
  <section id="your-first-c-api-extension-module">
<span id="first-extension-module"></span><span id="extending-simpleexample"></span><h1>Your first C API extension module<a class="headerlink" href="#your-first-c-api-extension-module" title="Link to this heading">¶</a></h1>
<p>This tutorial will take you through creating a simple
Python extension module written in C or C++.</p>
<p>We will use the low-level Python C API directly.
For easier ways to create extension modules, see
the <a class="reference internal" href="../c-api/intro.html#c-api-tools"><span class="std std-ref">recommended third party tools</span></a>.</p>
<p>The tutorial assumes basic knowledge about Python: you should be able to
define functions in Python code before starting to write them in C.
See <a class="reference internal" href="../tutorial/index.html#tutorial-index"><span class="std std-ref">The Python Tutorial</span></a> for an introduction to Python itself.</p>
<p>The tutorial should be approachable for anyone who can write a basic C library.
While we will mention several concepts that a C beginner would not be expected
to know, like <code class="docutils literal notranslate"><span class="pre">static</span></code> functions or linkage declarations, understanding these
is not necessary for success.</p>
<p>We will focus on giving you a “feel” of what Python’s C API is like.
It will not teach you important concepts, like error handling
and reference counting, which are covered in later chapters.</p>
<p>We will assume that you use a Unix-like system (including macOS and
Linux), or Windows.
On other systems, you might need to adjust some details – for example,
a system command name.</p>
<p>You need to have a suitable C compiler and Python development headers installed.
On Linux, headers are often in a package like <code class="docutils literal notranslate"><span class="pre">python3-dev</span></code>
or <code class="docutils literal notranslate"><span class="pre">python3-devel</span></code>.</p>
<p>You need to be able to install Python packages.
This tutorial uses <a class="reference external" href="https://pip.pypa.io/">pip</a> (<code class="docutils literal notranslate"><span class="pre">pip</span> <span class="pre">install</span></code>), but you
can substitute any tool that can build and install <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code>-based
projects, like <a class="reference external" href="https://docs.astral.sh/uv/">uv</a> (<code class="docutils literal notranslate"><span class="pre">uv</span> <span class="pre">pip</span> <span class="pre">install</span></code>).
Preferably, have a <a class="reference internal" href="../library/venv.html#venv-def"><span class="std std-ref">virtual environment</span></a> activated.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>This tutorial uses APIs that were added in CPython 3.15.
To create an extension that’s compatible with earlier versions of CPython,
please follow an earlier version of this documentation.</p>
<p>This tutorial uses C syntax added in C11 and C++20.
If your extension needs to be compatible with earlier standards,
please follow tutorials in documentation for Python 3.14 or below.</p>
</div>
<section id="what-we-ll-do">
<h2>What we’ll do<a class="headerlink" href="#what-we-ll-do" title="Link to this heading">¶</a></h2>
<p>Let’s create an extension module called <code class="docutils literal notranslate"><span class="pre">spam</span></code> <a class="footnote-reference brackets" href="#why-spam" id="id1" role="doc-noteref"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span></a>,
which will include a Python interface to the C
standard library function <code class="xref c c-func docutils literal notranslate"><span class="pre">system()</span></code>.
This function is defined in <code class="docutils literal notranslate"><span class="pre">stdlib.h</span></code>.
It takes a C string as argument, runs the argument as a system
command, and returns a result value as an integer.
A manual page for <code class="xref c c-func docutils literal notranslate"><span class="pre">system()</span></code> might summarize it this way:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#include</span><span class="w"> </span><span class="cpf">&lt;stdlib.h&gt;</span>
<span class="kt">int</span><span class="w"> </span><span class="nf">system</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">command</span><span class="p">);</span>
</pre></div>
</div>
<p>Note that like many functions in the C standard library,
this function is already exposed in Python.
In production, use <a class="reference internal" href="../library/os.html#os.system" title="os.system"><code class="xref py py-func docutils literal notranslate"><span class="pre">os.system()</span></code></a> or <a class="reference internal" href="../library/subprocess.html#subprocess.run" title="subprocess.run"><code class="xref py py-func docutils literal notranslate"><span class="pre">subprocess.run()</span></code></a>
rather than the module you’ll write here.</p>
<p>We want this function to be callable from Python as follows:</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span><span class="w"> </span><span class="nn">spam</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">status</span> <span class="o">=</span> <span class="n">spam</span><span class="o">.</span><span class="n">system</span><span class="p">(</span><span class="s2">&quot;whoami&quot;</span><span class="p">)</span>
<span class="go">User Name</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">status</span>
<span class="go">0</span>
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>The system command <code class="docutils literal notranslate"><span class="pre">whoami</span></code> prints out your username.
It’s useful in tutorials like this one because it has the same name on
both Unix and Windows.</p>
</div>
</section>
<section id="start-with-the-headers">
<h2>Start with the headers<a class="headerlink" href="#start-with-the-headers" title="Link to this heading">¶</a></h2>
<p>Begin by creating a directory for this tutorial, and switching to it
on the command line.
Then, create a file named <code class="file docutils literal notranslate"><span class="pre">spammodule.c</span></code> in your directory.
<a class="footnote-reference brackets" href="#why-spammodule" id="id2" role="doc-noteref"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span></a></p>
<p>In this file, we’ll include two headers: <code class="file docutils literal notranslate"><span class="pre">Python.h</span></code> to pull in
all declarations of the Python C API, and <code class="file docutils literal notranslate"><span class="pre">stdlib.h</span></code> for the
<code class="xref c c-func docutils literal notranslate"><span class="pre">system()</span></code> function. <a class="footnote-reference brackets" href="#stdlib-h" id="id3" role="doc-noteref"><span class="fn-bracket">[</span>3<span class="fn-bracket">]</span></a></p>
<p>Add the following lines to <code class="file docutils literal notranslate"><span class="pre">spammodule.c</span></code>:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#include</span><span class="w"> </span><span class="cpf">&lt;Python.h&gt;</span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf">&lt;stdlib.h&gt;</span><span class="w">     </span><span class="c1">// for system()</span>
</pre></div>
</div>
<p>Be sure to put <code class="file docutils literal notranslate"><span class="pre">stdlib.h</span></code>, and any other standard library includes,
<em>after</em> <code class="file docutils literal notranslate"><span class="pre">Python.h</span></code>.
On some systems, Python may define some pre-processor definitions
that affect the standard headers.</p>
</section>
<section id="running-your-build-tool">
<h2>Running your build tool<a class="headerlink" href="#running-your-build-tool" title="Link to this heading">¶</a></h2>
<p>With only the includes in place, your extension won’t do anything.
Still, it’s a good time to compile it and try to import it.
This will ensure that your build tool works, so that you can make
and test incremental changes as you follow the rest of the text.</p>
<p>CPython itself does not come with a tool to build extension modules;
it is recommended to use a third-party project for this.
In this tutorial, we’ll use <a class="reference external" href="https://mesonbuild.com/meson-python/">meson-python</a>.
(If you want to use another one, see <a class="reference internal" href="#first-extension-other-tools"><span class="std std-ref">Appendix: Other build tools</span></a>.)</p>
<p><code class="docutils literal notranslate"><span class="pre">meson-python</span></code> requires defining a “project” using two extra files.</p>
<p>First, add <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> with these contents:</p>
<div class="highlight-toml notranslate"><div class="highlight"><pre><span></span><span class="k">[build-system]</span>
<span class="n">build-backend</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#x27;mesonpy&#x27;</span>
<span class="n">requires</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="s1">&#x27;meson-python&#x27;</span><span class="p">]</span>

<span class="k">[project]</span>
<span class="c1"># Placeholder project information</span>
<span class="c1"># (change this before distributing the module)</span>
<span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#x27;sampleproject&#x27;</span>
<span class="n">version</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#x27;0&#x27;</span>
</pre></div>
</div>
<p>Then, create <code class="docutils literal notranslate"><span class="pre">meson.build</span></code> containing the following:</p>
<div class="highlight-meson notranslate"><div class="highlight"><pre><span></span><span class="nb">project</span><span class="p">(</span><span class="s">&#x27;sampleproject&#x27;</span><span class="p">,</span><span class="w"> </span><span class="s">&#x27;c&#x27;</span><span class="p">)</span>

<span class="n">py</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nn">import</span><span class="p">(</span><span class="s">&#x27;python&#x27;</span><span class="p">).</span><span class="n">find_installation</span><span class="p">(</span><span class="n">pure</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">)</span>

<span class="n">py</span><span class="p">.</span><span class="n">extension_module</span><span class="p">(</span>
<span class="w">   </span><span class="s">&#x27;spam&#x27;</span><span class="p">,</span><span class="w">          </span><span class="c"># name of the importable Python module</span>
<span class="w">   </span><span class="s">&#x27;spammodule.c&#x27;</span><span class="p">,</span><span class="w">  </span><span class="c"># the C source file</span>
<span class="w">   </span><span class="n">install</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span>
<span class="p">)</span>
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>See the <a class="reference external" href="https://mesonbuild.com/meson-python/">meson-python documentation</a> for details on
configuration.</p>
</div>
<p>Now, build install the <em>project in the current directory</em> (<code class="docutils literal notranslate"><span class="pre">.</span></code>) via <code class="docutils literal notranslate"><span class="pre">pip</span></code>:</p>
<div class="highlight-sh notranslate"><div class="highlight"><pre><span></span>python<span class="w"> </span>-m<span class="w"> </span>pip<span class="w"> </span>-v<span class="w"> </span>install<span class="w"> </span>.
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">-v</span></code> (<code class="docutils literal notranslate"><span class="pre">--verbose</span></code>) option causes <code class="docutils literal notranslate"><span class="pre">pip</span></code> to show the output from
the compiler, which is often useful during development.</p>
<div class="admonition tip">
<p class="admonition-title">Tip</p>
<p>If you don’t have <code class="docutils literal notranslate"><span class="pre">pip</span></code> installed, run <code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">-m</span> <span class="pre">ensurepip</span></code>,
preferably in a <a class="reference internal" href="../library/venv.html#venv-def"><span class="std std-ref">virtual environment</span></a>.
(Or, if you prefer another tool that can build and install
<code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code>-based projects, use that.)</p>
</div>
<p>Note that you will need to run this command again every time you change your
extension.
Unlike Python, C has an explicit compilation step.</p>
<p>When your extension is compiled and installed, start Python and try to
import it.
This should fail with the following exception:</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span><span class="w"> </span><span class="nn">spam</span>
<span class="gt">Traceback (most recent call last):</span>
<span class="w">   </span><span class="c">...</span>
<span class="gr">ImportError</span>: <span class="n">dynamic module does not define module export function (PyModExport_spam or PyInit_spam)</span>
</pre></div>
</div>
</section>
<section id="module-export-hook">
<h2>Module export hook<a class="headerlink" href="#module-export-hook" title="Link to this heading">¶</a></h2>
<p>The exception you got when you tried to import the module told you that Python
is looking for a “module export function”, also known as a
<a class="reference internal" href="../c-api/extension-modules.html#extension-export-hook"><span class="std std-ref">module export hook</span></a>.
Let’s define one.</p>
<p>First, add a prototype below the <code class="docutils literal notranslate"><span class="pre">#include</span></code> lines:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span>
<span class="n">PyMODEXPORT_FUNC</span><span class="w"> </span><span class="nf">PyModExport_spam</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span>

</pre></div>
</div>
<div class="admonition tip">
<p class="admonition-title">Tip</p>
<p>The prototype is not strictly necessary, but some modern compilers emit
warnings without it.
It’s generally better to add the prototype than to disable the warning.</p>
</div>
<p>The <a class="reference internal" href="../c-api/extension-modules.html#c.PyMODEXPORT_FUNC" title="PyMODEXPORT_FUNC"><code class="xref c c-macro docutils literal notranslate"><span class="pre">PyMODEXPORT_FUNC</span></code></a> macro declares the function’s
return type, and adds any special linkage declarations needed
to make the function visible and usable when CPython loads it.</p>
<p>After the prototype, add the function itself.
For now, make it return <code class="docutils literal notranslate"><span class="pre">NULL</span></code>:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">PyMODEXPORT_FUNC</span>
<span class="nf">PyModExport_spam</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">   </span><span class="k">return</span><span class="w"> </span><span class="nb">NULL</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Compile and load the module again.
You should get a different error this time.</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span><span class="w"> </span><span class="nn">spam</span>
<span class="gt">Traceback (most recent call last):</span>
<span class="w">   </span><span class="c">...</span>
<span class="gr">SystemError</span>: <span class="n">module export hook for module &#x27;spam&#x27; failed without setting an exception</span>
</pre></div>
</div>
<p>Simply returning <code class="docutils literal notranslate"><span class="pre">NULL</span></code> is <em>not</em> correct behavior for an export hook,
and CPython complains about it.
That’s good – it means that CPython found the function!
Let’s now make it do something useful.</p>
</section>
<section id="the-slot-table">
<h2>The slot table<a class="headerlink" href="#the-slot-table" title="Link to this heading">¶</a></h2>
<p>Rather than <code class="docutils literal notranslate"><span class="pre">NULL</span></code>, the export hook should return the information needed to
create a module.
Let’s start with the basics: the name and docstring.</p>
<p>The information should be defined in an array of
<a class="reference internal" href="../c-api/slots.html#c.PySlot" title="PySlot"><code class="xref c c-type docutils literal notranslate"><span class="pre">PySlot</span></code></a> entries, which are essentially key-value pairs.
Define this array just before your export hook:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">PyABIInfo_VAR</span><span class="p">(</span><span class="n">abi_info</span><span class="p">);</span>

<span class="k">static</span><span class="w"> </span><span class="n">PySlot</span><span class="w"> </span><span class="n">spam_slots</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">   </span><span class="n">PySlot_STATIC_DATA</span><span class="p">(</span><span class="n">Py_mod_abi</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">abi_info</span><span class="p">),</span>
<span class="w">   </span><span class="n">PySlot_STATIC_DATA</span><span class="p">(</span><span class="n">Py_mod_name</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;spam&quot;</span><span class="p">),</span>
<span class="w">   </span><span class="n">PySlot_STATIC_DATA</span><span class="p">(</span><span class="n">Py_mod_doc</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;A wonderful module with an example function&quot;</span><span class="p">),</span>
<span class="w">   </span><span class="n">PySlot_END</span>
<span class="p">};</span>
</pre></div>
</div>
<p>The <a class="reference internal" href="../c-api/slots.html#c.PySlot_STATIC_DATA" title="PySlot_STATIC_DATA"><code class="xref c c-macro docutils literal notranslate"><span class="pre">PySlot_STATIC_DATA</span></code></a> macro is used when the slot value
(here: <code class="docutils literal notranslate"><span class="pre">&amp;abi_info</span></code>, <code class="docutils literal notranslate"><span class="pre">&quot;spam&quot;</span></code>, and the docstring) is a pointer to constant,
statically allocated data.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">PyABIInfo_VAR(abi_info);</span></code> macro and the <a class="reference internal" href="../c-api/module.html#c.Py_mod_abi" title="Py_mod_abi"><code class="xref c c-data docutils literal notranslate"><span class="pre">Py_mod_abi</span></code></a> slot
are a bit of boilerplate that helps prevent extensions compiled for
a different version of Python from crashing the interpreter.</p>
<p>For both <a class="reference internal" href="../c-api/module.html#c.Py_mod_name" title="Py_mod_name"><code class="xref c c-data docutils literal notranslate"><span class="pre">Py_mod_name</span></code></a> and <a class="reference internal" href="../c-api/module.html#c.Py_mod_doc" title="Py_mod_doc"><code class="xref c c-data docutils literal notranslate"><span class="pre">Py_mod_doc</span></code></a>, the values are C
strings – that is, NUL-terminated, UTF-8 encoded byte arrays.</p>
<p>Note <code class="docutils literal notranslate"><span class="pre">PySlot_END</span></code> sentinel entry at the end.
This marks the end of the array.
If you forget it, you’ll trigger undefined behavior.</p>
<p>The array is defined as <code class="docutils literal notranslate"><span class="pre">static</span></code> – that is, not visible outside this <code class="docutils literal notranslate"><span class="pre">.c</span></code> file.
This will be a common theme.
CPython only needs to access the export hook; all global variables
and all other functions should generally be <code class="docutils literal notranslate"><span class="pre">static</span></code>, so that they don’t
clash with other extensions.</p>
<p>Return this array from your export hook instead of <code class="docutils literal notranslate"><span class="pre">NULL</span></code>:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">PyMODEXPORT_FUNC</span>
<span class="nf">PyModExport_spam</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="hll"><span class="w">   </span><span class="k">return</span><span class="w"> </span><span class="n">spam_slots</span><span class="p">;</span>
</span><span class="p">}</span>
</pre></div>
</div>
<p>Now, recompile and try it out:</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span><span class="w"> </span><span class="nn">spam</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">spam</span><span class="p">)</span>
<span class="go">&lt;module &#x27;spam&#x27; from &#x27;/home/encukou/dev/cpython/spam.so&#x27;&gt;</span>
</pre></div>
</div>
<p>You have an extension module!
Try <code class="docutils literal notranslate"><span class="pre">help(spam)</span></code> to see the docstring.</p>
<p>The next step will be adding a function.</p>
</section>
<section id="exposing-a-function">
<span id="backtoexample"></span><h2>Exposing a function<a class="headerlink" href="#exposing-a-function" title="Link to this heading">¶</a></h2>
<p>To expose the <code class="xref c c-func docutils literal notranslate"><span class="pre">system()</span></code> C function directly to Python,
we’ll need to write a layer of glue code to convert arguments from Python
objects to C values, and the C return value back to Python.</p>
<p>One of the simplest ways to write glue code is a “<a class="reference internal" href="../c-api/structures.html#c.METH_O" title="METH_O"><code class="xref c c-data docutils literal notranslate"><span class="pre">METH_O</span></code></a>” function,
which takes two Python objects and returns one.
All Python objects – regardless of the Python type – are represented in C
as pointers to the <a class="reference internal" href="../c-api/structures.html#c.PyObject" title="PyObject"><code class="xref c c-type docutils literal notranslate"><span class="pre">PyObject</span></code></a> structure.</p>
<p>Add such a function above the slots array:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span><span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span>
<span class="nf">spam_system</span><span class="p">(</span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">self</span><span class="p">,</span><span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">arg</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">   </span><span class="n">Py_RETURN_NONE</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
<p>For now, we ignore the arguments, and use the <a class="reference internal" href="../c-api/none.html#c.Py_RETURN_NONE" title="Py_RETURN_NONE"><code class="xref c c-macro docutils literal notranslate"><span class="pre">Py_RETURN_NONE</span></code></a>
macro, which expands to a <code class="docutils literal notranslate"><span class="pre">return</span></code> statement that properly returns
a Python <a class="reference internal" href="../library/constants.html#None" title="None"><code class="xref py py-data docutils literal notranslate"><span class="pre">None</span></code></a> object.</p>
<p>Recompile your extension to make sure you don’t have syntax errors.
We haven’t yet added <code class="docutils literal notranslate"><span class="pre">spam_system</span></code> to the module, so you might get a
warning that <code class="docutils literal notranslate"><span class="pre">spam_system</span></code> is unused.</p>
<section id="method-definitions">
<span id="methodtable"></span><h3>Method definitions<a class="headerlink" href="#method-definitions" title="Link to this heading">¶</a></h3>
<p>To expose the C function to Python, you will need to provide several pieces of
information in a structure called
<a class="reference internal" href="../c-api/structures.html#c.PyMethodDef" title="PyMethodDef"><code class="xref c c-type docutils literal notranslate"><span class="pre">PyMethodDef</span></code></a> <a class="footnote-reference brackets" href="#why-pymethoddef" id="id4" role="doc-noteref"><span class="fn-bracket">[</span>4<span class="fn-bracket">]</span></a>:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">ml_name</span></code>: the name of the Python function;</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">ml_doc</span></code>: a docstring;</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">ml_meth</span></code>: the C function to be called; and</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">ml_flags</span></code>: a set of flags describing details like how Python arguments are
passed to the C function.
We’ll use <a class="reference internal" href="../c-api/structures.html#c.METH_O" title="METH_O"><code class="xref c c-data docutils literal notranslate"><span class="pre">METH_O</span></code></a> here – the flag that matches our
<code class="docutils literal notranslate"><span class="pre">spam_system</span></code> function’s signature.</p></li>
</ul>
<p>Because modules typically create several functions, these definitions
need to be collected in an array, with a zero-filled sentinel at the end.
Add this array just below the <code class="docutils literal notranslate"><span class="pre">spam_system</span></code> function:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span>
<span class="k">static</span><span class="w"> </span><span class="n">PyMethodDef</span><span class="w"> </span><span class="n">spam_methods</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="p">.</span><span class="n">ml_name</span><span class="o">=</span><span class="s">&quot;system&quot;</span><span class="p">,</span>
<span class="w">        </span><span class="p">.</span><span class="n">ml_meth</span><span class="o">=</span><span class="n">spam_system</span><span class="p">,</span>
<span class="w">        </span><span class="p">.</span><span class="n">ml_flags</span><span class="o">=</span><span class="n">METH_O</span><span class="p">,</span>
<span class="w">        </span><span class="p">.</span><span class="n">ml_doc</span><span class="o">=</span><span class="s">&quot;Execute a shell command.&quot;</span><span class="p">,</span>
<span class="w">    </span><span class="p">},</span>
<span class="w">    </span><span class="p">{</span><span class="nb">NULL</span><span class="p">,</span><span class="w"> </span><span class="nb">NULL</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="nb">NULL</span><span class="p">}</span><span class="w">        </span><span class="cm">/* Sentinel */</span>
<span class="p">};</span>

</pre></div>
</div>
<p>As with module slots, a zero-filled sentinel marks the end of the array.</p>
<p>Next, we’ll add the method to the module.
Add a <a class="reference internal" href="../c-api/module.html#c.Py_mod_methods" title="Py_mod_methods"><code class="xref c c-data docutils literal notranslate"><span class="pre">Py_mod_methods</span></code></a> slot to your <a class="reference internal" href="../c-api/structures.html#c.PyMethodDef" title="PyMethodDef"><code class="xref c c-type docutils literal notranslate"><span class="pre">PyMethodDef</span></code></a> array:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span>
<span class="n">PyABIInfo_VAR</span><span class="p">(</span><span class="n">abi_info</span><span class="p">);</span>

<span class="k">static</span><span class="w"> </span><span class="n">PySlot</span><span class="w"> </span><span class="n">spam_slots</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="hll"><span class="w">    </span><span class="n">PySlot_STATIC_DATA</span><span class="p">(</span><span class="n">Py_mod_abi</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">abi_info</span><span class="p">),</span>
</span><span class="w">    </span><span class="n">PySlot_STATIC_DATA</span><span class="p">(</span><span class="n">Py_mod_name</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;spam&quot;</span><span class="p">),</span>
<span class="w">    </span><span class="n">PySlot_STATIC_DATA</span><span class="p">(</span><span class="n">Py_mod_doc</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;A wonderful module with an example function&quot;</span><span class="p">),</span>
<span class="w">    </span><span class="n">PySlot_STATIC_DATA</span><span class="p">(</span><span class="n">Py_mod_methods</span><span class="p">,</span><span class="w"> </span><span class="n">spam_methods</span><span class="p">),</span>
<span class="w">    </span><span class="n">PySlot_END</span>
<span class="p">};</span>

</pre></div>
</div>
<p>Recompile your extension again, and test it.
Be sure to restart the Python interpreter, so that <code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">spam</span></code> picks
up the new version of the module.</p>
<p>You should now be able to call the function:</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span><span class="w"> </span><span class="nn">spam</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">spam</span><span class="o">.</span><span class="n">system</span><span class="p">)</span>
<span class="go">&lt;built-in function system&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">spam</span><span class="o">.</span><span class="n">system</span><span class="p">(</span><span class="s1">&#x27;whoami&#x27;</span><span class="p">))</span>
<span class="go">None</span>
</pre></div>
</div>
<p>Note that our <code class="docutils literal notranslate"><span class="pre">spam.system</span></code> does not yet run the <code class="docutils literal notranslate"><span class="pre">whoami</span></code> command;
it only returns <code class="docutils literal notranslate"><span class="pre">None</span></code>.</p>
<p>Check that the function accepts exactly one argument, as specified by
the <a class="reference internal" href="../c-api/structures.html#c.METH_O" title="METH_O"><code class="xref c c-data docutils literal notranslate"><span class="pre">METH_O</span></code></a> flag:</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">spam</span><span class="o">.</span><span class="n">system</span><span class="p">(</span><span class="s1">&#x27;too&#x27;</span><span class="p">,</span> <span class="s1">&#x27;many&#x27;</span><span class="p">,</span> <span class="s1">&#x27;arguments&#x27;</span><span class="p">))</span>
<span class="gt">Traceback (most recent call last):</span>
<span class="w">   </span><span class="c">...</span>
<span class="gr">TypeError</span>: <span class="n">spam.system() takes exactly one argument (3 given)</span>
</pre></div>
</div>
</section>
</section>
<section id="returning-an-integer">
<h2>Returning an integer<a class="headerlink" href="#returning-an-integer" title="Link to this heading">¶</a></h2>
<p>Now, let’s take a look at the return value.
Instead of <code class="docutils literal notranslate"><span class="pre">None</span></code>, we’ll want <code class="docutils literal notranslate"><span class="pre">spam.system</span></code> to return a number – that is,
a Python <a class="reference internal" href="../library/functions.html#int" title="int"><code class="xref py py-type docutils literal notranslate"><span class="pre">int</span></code></a> object.
Eventually this will be the exit code of a system command,
but let’s start with a fixed value, say, <code class="docutils literal notranslate"><span class="pre">3</span></code>.</p>
<p>The Python C API provides a function to create a Python <a class="reference internal" href="../library/functions.html#int" title="int"><code class="xref py py-type docutils literal notranslate"><span class="pre">int</span></code></a> object
from a C <code class="docutils literal notranslate"><span class="pre">int</span></code> value: <a class="reference internal" href="../c-api/long.html#c.PyLong_FromLong" title="PyLong_FromLong"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyLong_FromLong()</span></code></a>. <a class="footnote-reference brackets" href="#why-pylongfromlong" id="id5" role="doc-noteref"><span class="fn-bracket">[</span>5<span class="fn-bracket">]</span></a></p>
<p>To call it, replace the <code class="docutils literal notranslate"><span class="pre">Py_RETURN_NONE</span></code> with the following 3 lines:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span><span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span>
<span class="nf">spam_system</span><span class="p">(</span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">self</span><span class="p">,</span><span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">arg</span><span class="p">)</span>
<span class="p">{</span>
<span class="hll"><span class="w">   </span><span class="kt">int</span><span class="w"> </span><span class="n">status</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">3</span><span class="p">;</span>
</span><span class="hll"><span class="w">   </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">PyLong_FromLong</span><span class="p">(</span><span class="n">status</span><span class="p">);</span>
</span><span class="hll"><span class="w">   </span><span class="k">return</span><span class="w"> </span><span class="n">result</span><span class="p">;</span>
</span><span class="p">}</span>
</pre></div>
</div>
<p>Recompile, restart the Python interpreter again,
and check that the function now returns 3:</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span><span class="w"> </span><span class="nn">spam</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">spam</span><span class="o">.</span><span class="n">system</span><span class="p">(</span><span class="s1">&#x27;whoami&#x27;</span><span class="p">)</span>
<span class="go">3</span>
</pre></div>
</div>
</section>
<section id="accepting-a-string">
<h2>Accepting a string<a class="headerlink" href="#accepting-a-string" title="Link to this heading">¶</a></h2>
<p>Finally, let’s handle the function argument.</p>
<p>Our C function, <code class="xref c c-func docutils literal notranslate"><span class="pre">spam_system()</span></code>, takes two arguments.
The first one, <code class="docutils literal notranslate"><span class="pre">PyObject</span> <span class="pre">*self</span></code>, will be set to the <code class="docutils literal notranslate"><span class="pre">spam</span></code> module
object.
This isn’t useful in our case, so we’ll ignore it.</p>
<p>The other one, <code class="docutils literal notranslate"><span class="pre">PyObject</span> <span class="pre">*arg</span></code>, will be set to the object that the user
passed from Python.
We expect that it should be a Python string.
In order to use the information in it, we will need
to convert it to a C value – in this case, a C string (<code class="docutils literal notranslate"><span class="pre">const</span> <span class="pre">char</span> <span class="pre">*</span></code>).</p>
<p>There’s a slight type mismatch here: Python’s <a class="reference internal" href="../library/stdtypes.html#str" title="str"><code class="xref py py-class docutils literal notranslate"><span class="pre">str</span></code></a> objects store
Unicode text, but C strings are arrays of bytes.
So, we’ll need to <em>encode</em> the data, and we’ll use the UTF-8 encoding for it.
(UTF-8 might not always be correct for system commands, but it’s what
<a class="reference internal" href="../library/stdtypes.html#str.encode" title="str.encode"><code class="xref py py-meth docutils literal notranslate"><span class="pre">str.encode()</span></code></a> uses by default,
and the C API has special support for it.)</p>
<p>The function to encode a Python string into a UTF-8 buffer is named
<a class="reference internal" href="../c-api/unicode.html#c.PyUnicode_AsUTF8AndSize" title="PyUnicode_AsUTF8AndSize"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyUnicode_AsUTF8AndSize()</span></code></a> <a class="footnote-reference brackets" href="#why-pyunicodeasutf8" id="id6" role="doc-noteref"><span class="fn-bracket">[</span>6<span class="fn-bracket">]</span></a>.
Call it like this:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span><span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span>
<span class="nf">spam_system</span><span class="p">(</span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">self</span><span class="p">,</span><span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">arg</span><span class="p">)</span>
<span class="p">{</span>
<span class="hll"><span class="w">   </span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">command</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">PyUnicode_AsUTF8AndSize</span><span class="p">(</span><span class="n">arg</span><span class="p">,</span><span class="w"> </span><span class="nb">NULL</span><span class="p">);</span>
</span><span class="w">   </span><span class="kt">int</span><span class="w"> </span><span class="n">status</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">3</span><span class="p">;</span>
<span class="w">   </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">PyLong_FromLong</span><span class="p">(</span><span class="n">status</span><span class="p">);</span>
<span class="w">   </span><span class="k">return</span><span class="w"> </span><span class="n">result</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
<p>If <a class="reference internal" href="../c-api/unicode.html#c.PyUnicode_AsUTF8AndSize" title="PyUnicode_AsUTF8AndSize"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyUnicode_AsUTF8AndSize()</span></code></a> is successful, <em>command</em> will point to the
resulting C string – a zero-terminated array of bytes <a class="footnote-reference brackets" href="#embedded-nul" id="id7" role="doc-noteref"><span class="fn-bracket">[</span>7<span class="fn-bracket">]</span></a>.
This buffer is managed by the <em>arg</em> object, which means we don’t need to free
it, but we must follow some rules:</p>
<ul class="simple">
<li><p>We should only use the buffer inside the <code class="docutils literal notranslate"><span class="pre">spam_system</span></code> function.
After <code class="docutils literal notranslate"><span class="pre">spam_system</span></code> returns, <em>arg</em> and the buffer it manages might be
garbage-collected.</p></li>
<li><p>We must not modify it. This is why we use <code class="docutils literal notranslate"><span class="pre">const</span></code>.</p></li>
</ul>
<p>If <a class="reference internal" href="../c-api/unicode.html#c.PyUnicode_AsUTF8AndSize" title="PyUnicode_AsUTF8AndSize"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyUnicode_AsUTF8AndSize()</span></code></a> was <em>not</em> successful, it returns a <code class="docutils literal notranslate"><span class="pre">NULL</span></code>
pointer.
When calling <em>any</em> Python C API, we always need to handle such error cases.
The way to do this in general is left for later chapters of this documentation.
For now, be assured that we are already handling errors from
<a class="reference internal" href="../c-api/long.html#c.PyLong_FromLong" title="PyLong_FromLong"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyLong_FromLong()</span></code></a> correctly.</p>
<p>For the <a class="reference internal" href="../c-api/unicode.html#c.PyUnicode_AsUTF8AndSize" title="PyUnicode_AsUTF8AndSize"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyUnicode_AsUTF8AndSize()</span></code></a> call, the correct way to handle
errors is returning <code class="docutils literal notranslate"><span class="pre">NULL</span></code> from <code class="docutils literal notranslate"><span class="pre">spam_system</span></code>.
Add an <code class="docutils literal notranslate"><span class="pre">if</span></code> block for this:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span><span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span>
<span class="nf">spam_system</span><span class="p">(</span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">self</span><span class="p">,</span><span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">arg</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">   </span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">command</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">PyUnicode_AsUTF8AndSize</span><span class="p">(</span><span class="n">arg</span><span class="p">);</span>
<span class="hll"><span class="w">   </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">command</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nb">NULL</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
</span><span class="hll"><span class="w">      </span><span class="k">return</span><span class="w"> </span><span class="nb">NULL</span><span class="p">;</span>
</span><span class="hll"><span class="w">   </span><span class="p">}</span>
</span><span class="w">   </span><span class="kt">int</span><span class="w"> </span><span class="n">status</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">3</span><span class="p">;</span>
<span class="w">   </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">PyLong_FromLong</span><span class="p">(</span><span class="n">status</span><span class="p">);</span>
<span class="w">   </span><span class="k">return</span><span class="w"> </span><span class="n">result</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
<p>To test that error handling works, compile again, restart Python so that
<code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">spam</span></code> picks up the new version of your module, and try passing
a non-string value to your function:</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span><span class="w"> </span><span class="nn">spam</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">spam</span><span class="o">.</span><span class="n">system</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
<span class="w">   </span><span class="c">...</span>
<span class="gr">TypeError</span>: <span class="n">bad argument type for built-in operation</span>
</pre></div>
</div>
<p>Now, all that is left is calling the C library function <code class="xref c c-func docutils literal notranslate"><span class="pre">system()</span></code> with
the <code class="docutils literal notranslate"><span class="pre">char</span> <span class="pre">*</span></code> buffer, and using its result instead of the <code class="docutils literal notranslate"><span class="pre">3</span></code>:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span><span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span>
<span class="nf">spam_system</span><span class="p">(</span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">self</span><span class="p">,</span><span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">arg</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">   </span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">command</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">PyUnicode_AsUTF8AndSize</span><span class="p">(</span><span class="n">arg</span><span class="p">);</span>
<span class="w">   </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">command</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nb">NULL</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">      </span><span class="k">return</span><span class="w"> </span><span class="nb">NULL</span><span class="p">;</span>
<span class="w">   </span><span class="p">}</span>
<span class="hll"><span class="w">   </span><span class="kt">int</span><span class="w"> </span><span class="n">status</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">system</span><span class="p">(</span><span class="n">command</span><span class="p">);</span>
</span><span class="w">   </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">PyLong_FromLong</span><span class="p">(</span><span class="n">status</span><span class="p">);</span>
<span class="w">   </span><span class="k">return</span><span class="w"> </span><span class="n">result</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Compile your module, restart Python, and test.
This time, you should see your username – the output of the <code class="docutils literal notranslate"><span class="pre">whoami</span></code>
system command:</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span><span class="w"> </span><span class="nn">spam</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">result</span> <span class="o">=</span> <span class="n">spam</span><span class="o">.</span><span class="n">system</span><span class="p">(</span><span class="s1">&#x27;whoami&#x27;</span><span class="p">)</span>
<span class="go">User Name</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">result</span>
<span class="go">0</span>
</pre></div>
</div>
<p>You can also test with other commands, like <code class="docutils literal notranslate"><span class="pre">ls</span></code>, <code class="docutils literal notranslate"><span class="pre">dir</span></code>, or one
that doesn’t exist:</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span><span class="w"> </span><span class="nn">spam</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">result</span> <span class="o">=</span> <span class="n">spam</span><span class="o">.</span><span class="n">system</span><span class="p">(</span><span class="s1">&#x27;nonexistent-command&#x27;</span><span class="p">)</span>
<span class="go">sh: line 1: nonexistent-command: command not found</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">result</span>
<span class="go">32512</span>
</pre></div>
</div>
</section>
<section id="the-result">
<h2>The result<a class="headerlink" href="#the-result" title="Link to this heading">¶</a></h2>
<p>Congratulations!
You have written a complete Python C API extension module,
and completed this tutorial!</p>
<p>Here is the entire source file, for your convenience:</p>
<div class="highlight-c notranslate" id="extending-spammodule-source"><div class="highlight"><pre><span></span><span class="c1">/// Includes</span>

<span class="cp">#include</span><span class="w"> </span><span class="cpf">&lt;Python.h&gt;</span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf">&lt;stdlib.h&gt;</span><span class="w">     </span><span class="c1">// for system()</span>

<span class="c1">/// Implementation of spam.system</span>

<span class="k">static</span><span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span>
<span class="nf">spam_system</span><span class="p">(</span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">self</span><span class="p">,</span><span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">arg</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">   </span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">command</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">PyUnicode_AsUTF8AndSize</span><span class="p">(</span><span class="n">arg</span><span class="p">,</span><span class="w"> </span><span class="nb">NULL</span><span class="p">);</span>
<span class="w">   </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">command</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nb">NULL</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">      </span><span class="k">return</span><span class="w"> </span><span class="nb">NULL</span><span class="p">;</span>
<span class="w">   </span><span class="p">}</span>
<span class="w">   </span><span class="kt">int</span><span class="w"> </span><span class="n">status</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">system</span><span class="p">(</span><span class="n">command</span><span class="p">);</span>
<span class="w">   </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">PyLong_FromLong</span><span class="p">(</span><span class="n">status</span><span class="p">);</span>
<span class="w">   </span><span class="k">return</span><span class="w"> </span><span class="n">result</span><span class="p">;</span>
<span class="p">}</span>

<span class="c1">/// Module method table</span>

<span class="k">static</span><span class="w"> </span><span class="n">PyMethodDef</span><span class="w"> </span><span class="n">spam_methods</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="p">.</span><span class="n">ml_name</span><span class="o">=</span><span class="s">&quot;system&quot;</span><span class="p">,</span>
<span class="w">        </span><span class="p">.</span><span class="n">ml_meth</span><span class="o">=</span><span class="n">spam_system</span><span class="p">,</span>
<span class="w">        </span><span class="p">.</span><span class="n">ml_flags</span><span class="o">=</span><span class="n">METH_O</span><span class="p">,</span>
<span class="w">        </span><span class="p">.</span><span class="n">ml_doc</span><span class="o">=</span><span class="s">&quot;Execute a shell command.&quot;</span><span class="p">,</span>
<span class="w">    </span><span class="p">},</span>
<span class="w">    </span><span class="p">{</span><span class="nb">NULL</span><span class="p">,</span><span class="w"> </span><span class="nb">NULL</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="nb">NULL</span><span class="p">}</span><span class="w">        </span><span class="cm">/* Sentinel */</span>
<span class="p">};</span>

<span class="c1">/// Module slot table</span>

<span class="n">PyABIInfo_VAR</span><span class="p">(</span><span class="n">abi_info</span><span class="p">);</span>

<span class="k">static</span><span class="w"> </span><span class="n">PySlot</span><span class="w"> </span><span class="n">spam_slots</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="n">PySlot_STATIC_DATA</span><span class="p">(</span><span class="n">Py_mod_abi</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">abi_info</span><span class="p">),</span>
<span class="w">    </span><span class="n">PySlot_STATIC_DATA</span><span class="p">(</span><span class="n">Py_mod_name</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;spam&quot;</span><span class="p">),</span>
<span class="w">    </span><span class="n">PySlot_STATIC_DATA</span><span class="p">(</span><span class="n">Py_mod_doc</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;A wonderful module with an example function&quot;</span><span class="p">),</span>
<span class="w">    </span><span class="n">PySlot_STATIC_DATA</span><span class="p">(</span><span class="n">Py_mod_methods</span><span class="p">,</span><span class="w"> </span><span class="n">spam_methods</span><span class="p">),</span>
<span class="w">    </span><span class="n">PySlot_END</span>
<span class="p">};</span>

<span class="c1">/// Export hook prototype</span>

<span class="n">PyMODEXPORT_FUNC</span><span class="w"> </span><span class="nf">PyModExport_spam</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span>

<span class="c1">/// Module export hook</span>

<span class="n">PyMODEXPORT_FUNC</span>
<span class="nf">PyModExport_spam</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">   </span><span class="k">return</span><span class="w"> </span><span class="n">spam_slots</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
</section>
<section id="appendix-other-build-tools">
<span id="first-extension-other-tools"></span><h2>Appendix: Other build tools<a class="headerlink" href="#appendix-other-build-tools" title="Link to this heading">¶</a></h2>
<p>You should be able to follow this tutorial – except the
<em>Running your build tool</em> section itself – with a build tool other
than <code class="docutils literal notranslate"><span class="pre">meson-python</span></code>.</p>
<p>The Python Packaging User Guide has a <a class="reference external" href="https://packaging.python.org/en/latest/guides/tool-recommendations/#build-backends-for-extension-modules">list of recommended tools</a>;
be sure to choose one for the C language.</p>
<section id="workaround-for-missing-pyinit-function">
<h3>Workaround for missing PyInit function<a class="headerlink" href="#workaround-for-missing-pyinit-function" title="Link to this heading">¶</a></h3>
<p>If your build tool output complains about missing <code class="docutils literal notranslate"><span class="pre">PyInit_spam</span></code>,
add the following function to your module for now:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="c1">// A workaround</span>
<span class="kt">void</span><span class="w"> </span><span class="o">*</span><span class="nf">PyInit_spam</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">NULL</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
</pre></div>
</div>
<p>This is a shim for an old-style <a class="reference internal" href="../c-api/extension-modules.html#extension-export-hook"><span class="std std-ref">initialization function</span></a>,
which was required in extension modules for CPython 3.14 and below.
Current CPython does not need it, but some build tools may still assume that
all extension modules need to define it.</p>
<p>If you use this workaround, you will get the exception
<code class="docutils literal notranslate"><span class="pre">SystemError:</span> <span class="pre">initialization</span> <span class="pre">of</span> <span class="pre">spam</span> <span class="pre">failed</span> <span class="pre">without</span> <span class="pre">raising</span> <span class="pre">an</span> <span class="pre">exception</span></code>
instead of
<code class="docutils literal notranslate"><span class="pre">ImportError:</span> <span class="pre">dynamic</span> <span class="pre">module</span> <span class="pre">does</span> <span class="pre">not</span> <span class="pre">define</span> <span class="pre">module</span> <span class="pre">export</span> <span class="pre">function</span></code>.</p>
</section>
<section id="compiling-directly">
<h3>Compiling directly<a class="headerlink" href="#compiling-directly" title="Link to this heading">¶</a></h3>
<p>Using a third-party build tool is heavily recommended,
as it will take care of various details of your platform and Python
installation, of naming the resulting extension, and, later, of distributing
your work.</p>
<p>If you are building an extension for as <em>specific</em> system, or for yourself
only, you might instead want to run your compiler directly.
The way to do this is system-specific; be prepared for issues you will need
to solve yourself.</p>
<section id="linux">
<h4>Linux<a class="headerlink" href="#linux" title="Link to this heading">¶</a></h4>
<p>On Linux, the Python development package may include a <code class="docutils literal notranslate"><span class="pre">python3-config</span></code>
command that prints out the required compiler flags.
If you use it, check that it corresponds to the CPython interpreter you’ll use
to load the module.
Then, start with the following command:</p>
<div class="highlight-sh notranslate"><div class="highlight"><pre><span></span>gcc<span class="w"> </span>--shared<span class="w"> </span><span class="k">$(</span>python3-config<span class="w"> </span>--cflags<span class="w"> </span>--ldflags<span class="k">)</span><span class="w"> </span>spammodule.c<span class="w"> </span>-o<span class="w"> </span>spam.so
</pre></div>
</div>
<p>This should generate a <code class="docutils literal notranslate"><span class="pre">spam.so</span></code> file that you need to put in a directory
on <a class="reference internal" href="../library/sys.html#sys.path" title="sys.path"><code class="xref py py-attr docutils literal notranslate"><span class="pre">sys.path</span></code></a>.</p>
<p class="rubric">Footnotes</p>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="why-spam" role="doc-footnote">
<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#id1">1</a><span class="fn-bracket">]</span></span>
<p><code class="docutils literal notranslate"><span class="pre">spam</span></code> is the favorite food of Monty Python fans…</p>
</aside>
<aside class="footnote brackets" id="why-spammodule" role="doc-footnote">
<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#id2">2</a><span class="fn-bracket">]</span></span>
<p>The source file name is entirely up to you,
though some tools can be picky about the <code class="docutils literal notranslate"><span class="pre">.c</span></code> extension.
This tutorial uses the traditional <code class="docutils literal notranslate"><span class="pre">*module.c</span></code> suffix.
Some people would just use <code class="file docutils literal notranslate"><span class="pre">spam.c</span></code> to implement a module
named <code class="docutils literal notranslate"><span class="pre">spam</span></code>,
projects where Python isn’t the primary language might use <code class="docutils literal notranslate"><span class="pre">py_spam.c</span></code>,
and so on.</p>
</aside>
<aside class="footnote brackets" id="stdlib-h" role="doc-footnote">
<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#id3">3</a><span class="fn-bracket">]</span></span>
<p>Including <code class="file docutils literal notranslate"><span class="pre">stdlib.h</span></code> is technically not necessary,
since <code class="file docutils literal notranslate"><span class="pre">Python.h</span></code> includes it and
<a class="reference internal" href="../c-api/intro.html#capi-system-includes"><span class="std std-ref">several other standard headers</span></a> for its own use
or for backwards compatibility.
However, it is good practice to explicitly include what you need.</p>
</aside>
<aside class="footnote brackets" id="why-pymethoddef" role="doc-footnote">
<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#id4">4</a><span class="fn-bracket">]</span></span>
<p>The <code class="xref c c-type docutils literal notranslate"><span class="pre">PyMethodDef</span></code> structure is also used
to create methods of classes, so there’s no separate
“<code class="xref c c-type docutils literal notranslate"><span class="pre">PyFunctionDef</span></code>”.</p>
</aside>
<aside class="footnote brackets" id="why-pylongfromlong" role="doc-footnote">
<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#id5">5</a><span class="fn-bracket">]</span></span>
<p>The name <a class="reference internal" href="../c-api/long.html#c.PyLong_FromLong" title="PyLong_FromLong"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyLong_FromLong()</span></code></a>
might not seem obvious.
<code class="docutils literal notranslate"><span class="pre">PyLong</span></code> refers to a the Python <a class="reference internal" href="../library/functions.html#int" title="int"><code class="xref py py-class docutils literal notranslate"><span class="pre">int</span></code></a>, which was originally
called <code class="docutils literal notranslate"><span class="pre">long</span></code>; the <code class="docutils literal notranslate"><span class="pre">FromLong</span></code> refers to the C <code class="docutils literal notranslate"><span class="pre">long</span></code> (or <code class="docutils literal notranslate"><span class="pre">long</span> <span class="pre">int</span></code>)
type.</p>
</aside>
<aside class="footnote brackets" id="why-pyunicodeasutf8" role="doc-footnote">
<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#id6">6</a><span class="fn-bracket">]</span></span>
<p>Here, <code class="docutils literal notranslate"><span class="pre">PyUnicode</span></code> refers to the original name of
the Python <a class="reference internal" href="../library/stdtypes.html#str" title="str"><code class="xref py py-class docutils literal notranslate"><span class="pre">str</span></code></a> class: <code class="docutils literal notranslate"><span class="pre">unicode</span></code>.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">AndSize</span></code> part of the name refers to the fact that this function can
also retrieve the size of the buffer, using an output argument.
We don’t need this, so we set the second argument to NULL.</p>
</aside>
<aside class="footnote brackets" id="embedded-nul" role="doc-footnote">
<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#id7">7</a><span class="fn-bracket">]</span></span>
<p>We’re ignoring the fact that Python strings can also
contain NUL bytes, which terminate a C string.
In other words, our function will treat <code class="docutils literal notranslate"><span class="pre">spam.system(&quot;foo\0bar&quot;)</span></code> as
<code class="docutils literal notranslate"><span class="pre">spam.system(&quot;foo&quot;)</span></code>.
This possibility can lead to security issues, so the real <code class="docutils literal notranslate"><span class="pre">os.system</span></code>
function size checks for this case and raises an error.</p>
</aside>
</aside>
</section>
</section>
</section>
</section>


            <div class="clearer"></div>
          </div>
        </div>
      </div>
      <div class="sphinxsidebar" role="navigation" aria-label="Main">
        <div class="sphinxsidebarwrapper">
  <div>
    <h3><a href="../contents.html">Table of Contents</a></h3>
    <ul>
<li><a class="reference internal" href="#">Your first C API extension module</a><ul>
<li><a class="reference internal" href="#what-we-ll-do">What we’ll do</a></li>
<li><a class="reference internal" href="#start-with-the-headers">Start with the headers</a></li>
<li><a class="reference internal" href="#running-your-build-tool">Running your build tool</a></li>
<li><a class="reference internal" href="#module-export-hook">Module export hook</a></li>
<li><a class="reference internal" href="#the-slot-table">The slot table</a></li>
<li><a class="reference internal" href="#exposing-a-function">Exposing a function</a><ul>
<li><a class="reference internal" href="#method-definitions">Method definitions</a></li>
</ul>
</li>
<li><a class="reference internal" href="#returning-an-integer">Returning an integer</a></li>
<li><a class="reference internal" href="#accepting-a-string">Accepting a string</a></li>
<li><a class="reference internal" href="#the-result">The result</a></li>
<li><a class="reference internal" href="#appendix-other-build-tools">Appendix: Other build tools</a><ul>
<li><a class="reference internal" href="#workaround-for-missing-pyinit-function">Workaround for missing PyInit function</a></li>
<li><a class="reference internal" href="#compiling-directly">Compiling directly</a><ul>
<li><a class="reference internal" href="#linux">Linux</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>

  </div>
  <div>
    <h4>Previous topic</h4>
    <p class="topless"><a href="index.html"
                          title="previous chapter">Extending and Embedding the Python Interpreter</a></p>
  </div>
  <div>
    <h4>Next topic</h4>
    <p class="topless"><a href="extending.html"
                          title="next chapter">Using the C API: Assorted topics</a></p>
  </div>
  <script>
    document.addEventListener('DOMContentLoaded', () => {
        const title = document.querySelector('meta[property="og:title"]').content;
        const elements = document.querySelectorAll('.improvepage');
        const pageurl = window.location.href.split('?')[0];
        elements.forEach(element => {
            const url = new URL(element.href.split('?')[0].replace("-nojs", ""));
            url.searchParams.set('pagetitle', title);
            url.searchParams.set('pageurl', pageurl);
            url.searchParams.set('pagesource', "extending/first-extension-module.rst");
            element.href = url.toString();
        });
    });
  </script>
  <div role="note" aria-label="source link">
    <h3>This page</h3>
    <ul class="this-page-menu">
      <li><a href="../bugs.html">Report a bug</a></li>
      <li><a class="improvepage" href="../improve-page-nojs.html">Improve this page</a></li>
      <li>
        <a href="https://github.com/python/cpython/blob/main/Doc/extending/first-extension-module.rst?plain=1"
            rel="nofollow">Show source
        </a>
      </li>
      
    </ul>
  </div>
        </div>
<div id="sidebarbutton" title="Collapse sidebar">
<span>«</span>
</div>

      </div>
      <div class="clearer"></div>
    </div>  
    <div class="related" role="navigation" aria-label="Related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="General Index"
             >index</a></li>
        <li class="right" >
          <a href="../py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li class="right" >
          <a href="extending.html" title="Using the C API: Assorted topics"
             >next</a> |</li>
        <li class="right" >
          <a href="index.html" title="Extending and Embedding the Python Interpreter"
             >previous</a> |</li>

          <li><img src="../_static/py.svg" alt="Python logo" style="vertical-align: middle; margin-top: -1px"></li>
          <li><a href="https://www.python.org/">Python</a> &#187;</li>
          <li class="switchers">
            <div class="language_switcher_placeholder"></div>
            <div class="version_switcher_placeholder"></div>
          </li>
          <li>
              
          </li>
    <li id="cpython-language-and-version">
      <a href="../index.html">3.15.0rc1 Documentation</a> &#187;
    </li>

          <li class="nav-item nav-item-1"><a href="index.html" >Extending and Embedding the Python Interpreter</a> &#187;</li>
        <li class="nav-item nav-item-this"><a href="">Your first C API extension module</a></li>
                <li class="right">
                    

    <div class="inline-search" role="search">
        <form class="inline-search" action="../search.html" method="get">
          <input placeholder="Quick search" aria-label="Quick search" type="search" name="q" id="search-box">
          <input type="submit" value="Go">
        </form>
    </div>
                     |
                </li>
            <li class="right">
<label class="theme-selector-label">
    Theme
    <select class="theme-selector" oninput="activateTheme(this.value)">
        <option value="auto" selected>Auto</option>
        <option value="light">Light</option>
        <option value="dark">Dark</option>
    </select>
</label> |</li>
            
      </ul>
    </div>  
    <div class="footer">
    &copy; <a href="../copyright.html">Copyright</a> 2001 Python Software Foundation.
    <br>
    This page is licensed under the Python Software Foundation License Version 2.
    <br>
    Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.
    <br>
    
      See <a href="/license.html">History and License</a> for more information.<br>
    
    
    <br>

    The Python Software Foundation is a non-profit corporation.
<a href="https://www.python.org/psf/donations/">Please donate.</a>
<br>
    <br>
      Last updated on Aug 04, 2026 (11:13 UTC).
    
      <a href="/bugs.html">Found a bug</a>?
    
    <br>

    Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.2.3.
    </div>

  </body>
</html>

Youez - 2016 - github.com/yon3zu
LinuXploit