<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Python on dev@iostream.pl</title><link>https://dev.iostream.pl/tags/python/</link><description>Recent content in Python on dev@iostream.pl</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Sun, 28 Jun 2026 16:08:00 +0200</lastBuildDate><atom:link href="https://dev.iostream.pl/tags/python/index.xml" rel="self" type="application/rss+xml"/><item><title>2026-06-28</title><link>https://dev.iostream.pl/posts/2026-06-28/</link><pubDate>Sun, 28 Jun 2026 16:08:00 +0200</pubDate><guid>https://dev.iostream.pl/posts/2026-06-28/</guid><description>&lt;h1 id="listbox-anyone"&gt;Listbox, anyone?
&lt;/h1&gt;&lt;p&gt;Many popular UI toolkits have their listbox control implemented to be as simple in use as possible. The most common operations are: creating the control, adding the data rows, deleting and editing data, handling the selection. Almost all toolkits provide single functions or suitable methods to realize above operations.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Gtk+&lt;/code&gt; is quite different: it requires more abstract way of thinking and additional objects to be created, but the lists and trees are more flexible and elegant.&lt;/p&gt;
&lt;h1 id="storing-the-data"&gt;Storing the data
&lt;/h1&gt;&lt;p&gt;Before we can display a single string, let&amp;rsquo;s first earn a PhD in data models.&lt;/p&gt;
&lt;p&gt;Unlike the the other toolkits, the gtk+ list allows to display a few values per a row. Gtk+ list also distinguishes between the types of data, while other lists treat its row data as a single string.&lt;/p&gt;
&lt;p&gt;In fact, the &lt;code&gt;TreeView&lt;/code&gt; widget will be used to display elements. The model lets the display widget know about data types to be used in the control, it also determines the type of the control (if it should be a list or a tree). Besides, the model is used to store all the data (it is common to find a &amp;ldquo;store&amp;rdquo; term instead of &amp;ldquo;model&amp;rdquo; in various papers or in someone&amp;rsquo;s code)&lt;/p&gt;
&lt;p&gt;A store/model can be created by calling a proper constructor with at least one data type (to be used in the list) as argument:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;store &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;ListStore(type1, &lt;span style="color:#f92672"&gt;...&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;store &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;ListStore(int, str, str)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Created store will contain one integer value and two strings per row. Although pygtk reference recommends to use build-in GObject types (for instance, gobject.TYPE_INT and gobject.TYPE_STRING instead of int and str respectively), python built-in types are also allowed (GObject names really matter in C or C++)&lt;/p&gt;
&lt;h1 id="adding-the-data-rows"&gt;Adding the data rows
&lt;/h1&gt;&lt;p&gt;The method append from Gtk.ListStore class allows to append one row at the end of the store. Sequence with all values should be passed as a parameter:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;store&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append([val1, &lt;span style="color:#f92672"&gt;...&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;store&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append([&lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;str1&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;str2&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="columns-and-renderers"&gt;Columns and renderers
&lt;/h1&gt;&lt;p&gt;Control widget should know about columns it should display, their order and how to present data from the store. Gtk+ provides the column widget (Gtk.TreeViewColumn) to manage displaying the cells of data and renderer widgets (Gtk.CellRenderer and its derivatives) to realize rendering of particular cells.&lt;/p&gt;
&lt;p&gt;Column widget is usually created by calling a constructor of &lt;code&gt;Gtk.TreeViewColumn&lt;/code&gt; with a header title passed as the argument:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;column &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;TreeViewColumn(title)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;column &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;TreeViewColumn(&lt;span style="color:#e6db74"&gt;&amp;#34;Column header&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Column header is visible by default — passing an empty string to the constructor will not get rid of it.&lt;/p&gt;
&lt;p&gt;Cell renderer should be one of &lt;code&gt;Gtk.CellRendererAccel&lt;/code&gt;, &lt;code&gt;Gtk.CellRendererCombo&lt;/code&gt;, &lt;code&gt;Gtk.CellRendererPixbuf&lt;/code&gt;, &lt;code&gt;Gtk.CellRendererProgress&lt;/code&gt;, &lt;code&gt;Gtk.CellRendererSpin&lt;/code&gt;, &lt;code&gt;Gtk.CellRendererText&lt;/code&gt;, &lt;code&gt;Gtk.CellRendererToggle&lt;/code&gt;. The renderer object is usually created by calling the constructor with no parameters&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;renderer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;CellRendererText()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Renderers should be added to the column widgets: pack_start and pack_end methods are used to do the packing.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;column&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pack_start(renderer)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;or&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;column&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pack_end(renderer)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;column1 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;TreeViewColumn(&lt;span style="color:#e6db74"&gt;&amp;#34;Column1&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;renderer1 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;CellRendererText()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;renderer2 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;CellRendererText()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;renderer3 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;CellRendererText()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;column1&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pack_start(renderer1)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;column1&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pack_start(renderer2)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;column1&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pack_end(renderer3)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The column widget must know which data column from the model should be connected to any of these renderers. This could be done by calling set_attributes method:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;column&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_attributes(renderer, &lt;span style="color:#f92672"&gt;...&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;All optional parameters are &amp;ldquo;key = value&amp;rdquo; pairs, where key is the data type and value is number of column in the store&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;column1&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_attributes(renderer1, text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;column1&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_attributes(renderer2, text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;column1&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_attributes(renderer3, text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="treeview-control"&gt;TreeView control
&lt;/h1&gt;&lt;p&gt;The last step is to create a control and add all columns. Constructor of the control takes the store as first parameter:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;listControl &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;TreeView(model&lt;span style="color:#f92672"&gt;=&lt;/span&gt;store)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The method append_column adds given column to the tree/list control:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;listControl&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append_column(column)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Summary: at least, four objects should be created to have the tree/list control working: a model which determines types of data and stores all the rows, a renderer, which takes care of displaying the cells, a column, which glues together model columns and suitable renderers and a treeview control itself.&lt;/p&gt;
&lt;h1 id="working-examples"&gt;Working examples
&lt;/h1&gt;&lt;p&gt;Following examples illustrate the creation and displaying of the lists.&lt;/p&gt;
&lt;h2 id="very-simple-list-control"&gt;Very simple list control
&lt;/h2&gt;&lt;p&gt;The simplest list control contains only one column and displays only one value per row&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#!/usr/bin/env python3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; gi
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;gi&lt;span style="color:#f92672"&gt;.&lt;/span&gt;require_version(&lt;span style="color:#e6db74"&gt;&amp;#34;Gtk&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;3.0&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;from&lt;/span&gt; gi.repository &lt;span style="color:#f92672"&gt;import&lt;/span&gt; Gtk
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ListBoxViewer1&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;destroyCallback&lt;/span&gt;(self, widget, data&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;None&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;main_quit()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;__init__&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listStore &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;ListStore(str)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listStore&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append([&lt;span style="color:#e6db74"&gt;&amp;#34;String 1&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listStore&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append([&lt;span style="color:#e6db74"&gt;&amp;#34;String 2&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listStore&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append([&lt;span style="color:#e6db74"&gt;&amp;#34;String 3&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listStore&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append([&lt;span style="color:#e6db74"&gt;&amp;#34;String 4&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listStore&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append([&lt;span style="color:#e6db74"&gt;&amp;#34;String 5&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;TreeViewColumn(&lt;span style="color:#e6db74"&gt;&amp;#34;Sample column&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;textRenderer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;CellRendererText()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pack_start(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;textRenderer, &lt;span style="color:#66d9ef"&gt;True&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_attributes(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;textRenderer, text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;mainWindow &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;Window(type&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;WindowType&lt;span style="color:#f92672"&gt;.&lt;/span&gt;TOPLEVEL)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;mainWindow&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_title(&lt;span style="color:#e6db74"&gt;&amp;#39;ListBoxViewer1&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listBox &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;TreeView(model&lt;span style="color:#f92672"&gt;=&lt;/span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listStore)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listBox&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append_column(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;mainWindow&lt;span style="color:#f92672"&gt;.&lt;/span&gt;add(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listBox)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;mainWindow&lt;span style="color:#f92672"&gt;.&lt;/span&gt;connect(&lt;span style="color:#e6db74"&gt;&amp;#39;delete_event&amp;#39;&lt;/span&gt;, self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;destroyCallback)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;mainWindow&lt;span style="color:#f92672"&gt;.&lt;/span&gt;show_all()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; __name__ &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; lbv1 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ListBoxViewer1()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;main()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This example covers the theory of creating listboxes with additional routines necessary to run minimal gtk+ program. Additional method is added to provide termination of this example when its window has been closed.&lt;/p&gt;
&lt;p&gt;All list-related routines are explained below:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listStore &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;ListStore(str)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listStore&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append([&lt;span style="color:#e6db74"&gt;&amp;#34;String 1&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listStore&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append([&lt;span style="color:#e6db74"&gt;&amp;#34;String 2&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listStore&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append([&lt;span style="color:#e6db74"&gt;&amp;#34;String 3&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listStore&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append([&lt;span style="color:#e6db74"&gt;&amp;#34;String 4&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listStore&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append([&lt;span style="color:#e6db74"&gt;&amp;#34;String 5&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The model is created: it can hold one string value per a row. Then it is populated by 5 rows.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;textRenderer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;CellRendererText()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Text renderer is created.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;TreeViewColumn(&lt;span style="color:#e6db74"&gt;&amp;#34;Sample column&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pack_start(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;textRenderer, &lt;span style="color:#66d9ef"&gt;True&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_attributes(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;textRenderer, text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A column is created. Then the renderer is packed into the column, and the column is informed which column and what type of data from the store will be used.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listBox &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;TreeView(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listStore)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listBox&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append_column(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Main widget is created. The column is appended to the list.&lt;/p&gt;
&lt;p&gt;It looks like the following:&lt;/p&gt;
&lt;p&gt;&lt;img alt="ListboxViewer 1" class="gallery-image" data-flex-basis="224px" data-flex-grow="93" height="333" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://dev.iostream.pl/posts/2026-06-28/listbox-1.png" width="312"&gt;&lt;/p&gt;
&lt;p&gt;Explanation of the next examples contains only the routines related to list control; other routines did not change if not mentioned.&lt;/p&gt;
&lt;h2 id="two-values-per-row"&gt;Two values per row
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listStore &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;ListStore(str, int)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listStore&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append([&lt;span style="color:#e6db74"&gt;&amp;#34;String 1&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;18000&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listStore&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append([&lt;span style="color:#e6db74"&gt;&amp;#34;String 2&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1500&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listStore&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append([&lt;span style="color:#e6db74"&gt;&amp;#34;String 3&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;900&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listStore&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append([&lt;span style="color:#e6db74"&gt;&amp;#34;String 4&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;60&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listStore&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append([&lt;span style="color:#e6db74"&gt;&amp;#34;String 5&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now the store holds a string an integer pair per a row.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;TreeViewColumn(&lt;span style="color:#e6db74"&gt;&amp;#34;Sample column&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;textRenderer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;CellRendererText()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;numRenderer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;CellRendererText()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;numRenderer&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_property(&lt;span style="color:#e6db74"&gt;&amp;#39;xalign&amp;#39;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1.0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A column and two cell renderers are created. The set_property routine with xalign property to be set tells the renderer to align right the values in the row. Value of 0.0 means left alignment, 0.5 centers the text and 1.0 means right alignment.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pack_start(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;textRenderer, &lt;span style="color:#66d9ef"&gt;True&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pack_start(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;numRenderer, &lt;span style="color:#66d9ef"&gt;False&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_attributes(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;textRenderer, text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_attributes(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;numRenderer, text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The two renderers are packed into the column. The string value renderer will expand the cell if possible. Proper renderers are assigned to proper data columns from the store.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listBox &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;TreeView(store&lt;span style="color:#f92672"&gt;=&lt;/span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listStore)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listBox&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append_column(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The control is created and the column is appended to the control.&lt;/p&gt;
&lt;p&gt;The following picture shows the result of this example:&lt;/p&gt;
&lt;p&gt;&lt;img alt="ListboxViewer 2" class="gallery-image" data-flex-basis="265px" data-flex-grow="110" height="240" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://dev.iostream.pl/posts/2026-06-28/listbox-2.png" width="265"&gt;&lt;/p&gt;
&lt;h2 id="two-columns-in-the-control"&gt;Two columns in the control
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn1 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;TreeViewColumn(&lt;span style="color:#e6db74"&gt;&amp;#34;Ascii text&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn2 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;TreeViewColumn(&lt;span style="color:#e6db74"&gt;&amp;#34;Numeric value&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;textRenderer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;CellRendererText()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;numRenderer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;CellRendererText()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;numRenderer&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_property(&lt;span style="color:#e6db74"&gt;&amp;#39;xalign&amp;#39;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1.0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn1&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pack_start(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;textRenderer, &lt;span style="color:#66d9ef"&gt;True&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn2&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pack_start(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;numRenderer, &lt;span style="color:#66d9ef"&gt;False&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn1&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_attributes(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;textRenderer, text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn2&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_attributes(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;numRenderer, text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Every column packs one of the renderes. It looks like the following:&lt;/p&gt;
&lt;p&gt;&lt;img alt="ListboxViewer 3" class="gallery-image" data-flex-basis="222px" data-flex-grow="92" height="219" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://dev.iostream.pl/posts/2026-06-28/listbox-3.png" width="203"&gt;&lt;/p&gt;
&lt;h2 id="adding-pixmaps-to-the-list"&gt;Adding pixmaps to the list
&lt;/h2&gt;&lt;p&gt;Now, creating the store is like below:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sheetIcon &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;gdk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pixbuf_new_from_file(&lt;span style="color:#e6db74"&gt;&amp;#34;sheet.xpm&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listStore &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;ListStore(str, int, Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;gdk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;Pixbuf)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listStore&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append([&lt;span style="color:#e6db74"&gt;&amp;#34;String 1&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;18000&lt;/span&gt;, self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sheetIcon])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listStore&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append([&lt;span style="color:#e6db74"&gt;&amp;#34;String 2&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1500&lt;/span&gt;, self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sheetIcon])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listStore&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append([&lt;span style="color:#e6db74"&gt;&amp;#34;String 3&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;900&lt;/span&gt;, self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sheetIcon])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listStore&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append([&lt;span style="color:#e6db74"&gt;&amp;#34;String 4&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;60&lt;/span&gt;, self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sheetIcon])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listStore&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append([&lt;span style="color:#e6db74"&gt;&amp;#34;String 5&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sheetIcon])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The pixbuf is added in every row. Of course, it may be different in every row. This is only the example.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;iconRenderer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;CellRendererPixbuf()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The icon requires a special kind of cell renderer.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn1&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pack_start(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;iconRenderer, &lt;span style="color:#66d9ef"&gt;False&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn1&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_attributes(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;iconRenderer, pixbuf &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Pixbuf cell renderer is now packed into the first column together with the text renderer.&lt;/p&gt;
&lt;p&gt;It looks like the following:&lt;/p&gt;
&lt;p&gt;&lt;img alt="ListboxViewer 4" class="gallery-image" data-flex-basis="125px" data-flex-grow="52" height="465" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://dev.iostream.pl/posts/2026-06-28/listbox-4.png" width="244"&gt;&lt;/p&gt;
&lt;h2 id="display-the-same-values-twice-or-more-times"&gt;Display the same values twice or more times
&lt;/h2&gt;&lt;p&gt;Displaying more values per row is achieved by multiplicating the renderes:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn1 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;TreeViewColumn(&lt;span style="color:#e6db74"&gt;&amp;#34;Ascii text&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn2 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;TreeViewColumn(&lt;span style="color:#e6db74"&gt;&amp;#34;Numeric value&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;textRenderer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;CellRendererText()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;textRenderer2 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;CellRendererText()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;numRenderer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;CellRendererText()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;numRenderer2 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;CellRendererText()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;numRenderer3 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;CellRendererText()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;iconRenderer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;CellRendererPixbuf()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;iconRenderer2 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Gtk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;CellRendererPixbuf()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;numRenderer&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_property(&lt;span style="color:#e6db74"&gt;&amp;#39;xalign&amp;#39;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1.0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;numRenderer2&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_property(&lt;span style="color:#e6db74"&gt;&amp;#39;xalign&amp;#39;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0.0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;numRenderer2&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_property(&lt;span style="color:#e6db74"&gt;&amp;#39;xalign&amp;#39;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0.5&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;textRenderer2&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_property(&lt;span style="color:#e6db74"&gt;&amp;#39;xalign&amp;#39;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1.0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn1&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pack_start(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;iconRenderer, &lt;span style="color:#66d9ef"&gt;False&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn1&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pack_start(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;textRenderer, &lt;span style="color:#66d9ef"&gt;True&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn2&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pack_start(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;numRenderer, &lt;span style="color:#66d9ef"&gt;False&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn2&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pack_start(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;numRenderer2, &lt;span style="color:#66d9ef"&gt;False&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn2&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pack_start(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;iconRenderer2, &lt;span style="color:#66d9ef"&gt;False&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn2&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pack_start(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;numRenderer3, &lt;span style="color:#66d9ef"&gt;False&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn2&lt;span style="color:#f92672"&gt;.&lt;/span&gt;pack_start(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;textRenderer2, &lt;span style="color:#66d9ef"&gt;True&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn1&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_attributes(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;iconRenderer, pixbuf &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn1&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_attributes(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;textRenderer, text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn2&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_attributes(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;numRenderer, text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn2&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_attributes(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;numRenderer2, text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn2&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_attributes(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;numRenderer3, text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn2&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_attributes(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;textRenderer2, text &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;listColumn2&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_attributes(self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;iconRenderer2, pixbuf &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Also, the left, right and center alignment of text is shown.&lt;/p&gt;
&lt;p&gt;It looks like the following:&lt;/p&gt;
&lt;p&gt;&lt;img alt="ListboxViewer 5" class="gallery-image" data-flex-basis="209px" data-flex-grow="87" height="511" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://dev.iostream.pl/posts/2026-06-28/listbox-5.png" width="447"&gt;&lt;/p&gt;</description></item><item><title>2026-06-22</title><link>https://dev.iostream.pl/posts/2026-06-22/</link><pubDate>Mon, 22 Jun 2026 20:05:00 +0200</pubDate><guid>https://dev.iostream.pl/posts/2026-06-22/</guid><description>
 &lt;blockquote&gt;
 &lt;p&gt;The original version of this article was written in 2006.&lt;/p&gt;
&lt;p&gt;Back then:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Python 2 was still alive,&lt;/li&gt;
&lt;li&gt;distutils existed,&lt;/li&gt;
&lt;li&gt;XEmacs was technically not dead,&lt;/li&gt;
&lt;li&gt;and people still owned VHS tapes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&amp;rsquo;s see how much of this still works in 2026.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h1 id="modules-lies-and-vhs-tapes"&gt;Modules, Lies, and VHS Tapes
&lt;/h1&gt;&lt;p&gt;Sometimes you need to write Python bindings for a strange third-party library. It happens.&lt;/p&gt;
&lt;p&gt;Sometimes you need to write the library itself. That happens too.&lt;/p&gt;
&lt;p&gt;And sometimes you have to do all of that on Windows using GNU tools.&lt;/p&gt;
&lt;p&gt;This article serves both as a professional tutorial and as a public service announcement suggesting that you abandon everything and move to a remote mountain cabin. Mostly because I can never remember the correct order of the steps involved.&lt;/p&gt;
&lt;h2 id="prerequisites-on-windows"&gt;Prerequisites on Windows
&lt;/h2&gt;&lt;p&gt;The easiest approach is to use MSYS2 and GCC.&lt;/p&gt;
&lt;p&gt;You should have the following tools available somewhere in your PATH:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GCC&lt;/li&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dlltool&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nothing particularly exotic.&lt;/p&gt;
&lt;h2 id="a-sample-library"&gt;A Sample Library
&lt;/h2&gt;&lt;p&gt;Our example library is intentionally simple. It contains only two functions: one that adds two integers and one that multiplies them.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mul2x&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; x, &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; y)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; x &lt;span style="color:#f92672"&gt;*&lt;/span&gt; y;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;add2x&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; x, &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; y)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; x &lt;span style="color:#f92672"&gt;+&lt;/span&gt; y;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Since the library is simple, let&amp;rsquo;s call it &lt;code&gt;SimpLib&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Assume the source code is stored in a file called &lt;code&gt;simplib.c&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="building-the-library"&gt;Building the Library
&lt;/h2&gt;&lt;p&gt;As always, source files should first be compiled into object files.&lt;/p&gt;
&lt;p&gt;To produce a shared library, GCC requires the &lt;code&gt;-shared&lt;/code&gt; option.&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;Following Unix naming conventions, shared libraries usually have a &lt;code&gt;lib&lt;/code&gt; prefix and a &lt;code&gt;.so&lt;/code&gt; extension. Linking with &lt;code&gt;-lname&lt;/code&gt; assumes the presence of a library named &lt;code&gt;libname.so&lt;/code&gt; somewhere on the library search path. Many GNU projects ported to Windows continue to use this naming convention internally, even though the final artifact is a &lt;code&gt;.dll&lt;/code&gt;.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h3 id="linux"&gt;Linux
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;gcc -o simplib.o -c simplib.c
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;gcc -o libsimp.so simplib.o -shared
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Of course, for a single source file you could simply write:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;gcc -o libsimp.so simplib.c -shared
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, once a project grows beyond a trivial example, compiling each source file separately and linking everything at the end is usually a much better idea.&lt;/p&gt;
&lt;p&gt;Congratulations. The library has been built and is ready for use.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Cue triumphant fanfare.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id="windows"&gt;Windows
&lt;/h3&gt;&lt;p&gt;Although we&amp;rsquo;re using exactly the same compiler, Windows requires one additional step.&lt;/p&gt;
&lt;p&gt;We need to create an &lt;strong&gt;import library&lt;/strong&gt; (sometimes called an interface library) that other applications can link against. This is where &lt;code&gt;dlltool&lt;/code&gt; enters the picture.&lt;/p&gt;
&lt;h4 id="creating-the-import-library"&gt;Creating the Import Library
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;gcc -o simplib.o -c simplib.c
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dlltool -l libsimp.lib simplib.o
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;gcc -o libsimp.dll simplib.o -shared
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The DLL is now ready.&lt;/p&gt;
&lt;p&gt;The import library is also ready.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Cue Windows-themed fanfare.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="header-file"&gt;Header File
&lt;/h2&gt;&lt;p&gt;Providing a header file is generally considered a polite thing to do.&lt;/p&gt;
&lt;p&gt;Other developers will appreciate not having to reverse-engineer your function declarations, and they will be less inclined to say unpleasant things about you.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#ifndef __SIMPLIB_H__
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define __SIMPLIB_H__
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mul2x&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; x, &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; y);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;add2x&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; x, &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; y);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#endif
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Assume this file is called &lt;code&gt;simplib.h&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="a-sample-c-program"&gt;A Sample C Program
&lt;/h2&gt;&lt;p&gt;The best way to test a library is to write a small program that uses it.&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;There are not many activities one can perform while fully clothed that are more enjoyable than programming, although surprisingly few people seem aware of this fact.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;#34;simplib.h&amp;#34;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; argc, &lt;span style="color:#66d9ef"&gt;char&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;argv[])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Adding 5 to 10: %d&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;add2x&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Multiplying 5 by 10: %d&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;mul2x&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Assume this program is stored as &lt;code&gt;simprg.c&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="building-the-sample-program"&gt;Building the Sample Program
&lt;/h2&gt;&lt;h3 id="linux-1"&gt;Linux
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;gcc -o simprg.o -c simprg.c
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;gcc -o simprg simprg.o -lsimp
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="windows-1"&gt;Windows
&lt;/h3&gt;&lt;p&gt;Remember the import library:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;gcc -o simprg.o -c simprg.c
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;gcc -o simprg simprg.o libsimp.lib -lsimp
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="a-brief-note-about-flags"&gt;A Brief Note About Flags
&lt;/h3&gt;&lt;p&gt;If the library is not located on the system library search path, remember to use the &lt;code&gt;-L&lt;/code&gt; option.&lt;/p&gt;
&lt;p&gt;Windows searches the current directory by default.&lt;/p&gt;
&lt;p&gt;Linux does not.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;gcc -o simprg simprg.o -L. -lsimp
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="writing-a-python-extension-module"&gt;Writing a Python Extension Module
&lt;/h2&gt;
 &lt;blockquote&gt;
 &lt;p&gt;Historical note&lt;/p&gt;
&lt;p&gt;The code below targets Python 2.x and reflects the state of the CPython API around 2006.
Modern Python 3 extension modules use a different initialization mechanism based on
&lt;code&gt;PyModuleDef&lt;/code&gt; and &lt;code&gt;PyModule_Create&lt;/code&gt;.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;The following code demonstrates Python bindings for &lt;code&gt;SimpLib&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;Python.h&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;#34;simplib.h&amp;#34;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; PyObject &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;simp_mul2x&lt;/span&gt;(PyObject &lt;span style="color:#f92672"&gt;*&lt;/span&gt;self, PyObject &lt;span style="color:#f92672"&gt;*&lt;/span&gt;args)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; x, y, result;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; PyObject &lt;span style="color:#f92672"&gt;*&lt;/span&gt;pyresult;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;PyArg_ParseTuple&lt;/span&gt;(args, &lt;span style="color:#e6db74"&gt;&amp;#34;ii&amp;#34;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;x;, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;y;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; NULL;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; result &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mul2x&lt;/span&gt;(x, y);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pyresult &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Py_BuildValue&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;i&amp;#34;&lt;/span&gt;, result);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; pyresult;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; PyObject &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;simp_add2x&lt;/span&gt;(PyObject &lt;span style="color:#f92672"&gt;*&lt;/span&gt;self, PyObject &lt;span style="color:#f92672"&gt;*&lt;/span&gt;args)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; x, y, result;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; PyObject &lt;span style="color:#f92672"&gt;*&lt;/span&gt;pyresult;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;PyArg_ParseTuple&lt;/span&gt;(args, &lt;span style="color:#e6db74"&gt;&amp;#34;ii&amp;#34;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;x;, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;y;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; NULL;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; result &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;add2x&lt;/span&gt;(x, y);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pyresult &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Py_BuildValue&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;i&amp;#34;&lt;/span&gt;, result);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; pyresult;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; PyMethodDef SimpMethods[] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&lt;span style="color:#e6db74"&gt;&amp;#34;mul2x&amp;#34;&lt;/span&gt;, simp_mul2x, METH_VARARGS, &lt;span style="color:#e6db74"&gt;&amp;#34;Multiply two integer values&amp;#34;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&lt;span style="color:#e6db74"&gt;&amp;#34;add2x&amp;#34;&lt;/span&gt;, simp_add2x, METH_VARARGS, &lt;span style="color:#e6db74"&gt;&amp;#34;Add two integer values&amp;#34;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {NULL, NULL, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, NULL}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PyMODINIT_FUNC &lt;span style="color:#a6e22e"&gt;initsimp&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;Py_InitModule&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;simp&amp;#34;&lt;/span&gt;, SimpMethods);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Assume the file is called &lt;code&gt;simpmodule.c&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="what-is-happening-here"&gt;What Is Happening Here?
&lt;/h3&gt;&lt;p&gt;Every extension module requires an initialization function.&lt;/p&gt;
&lt;p&gt;Historically, for Python 2.x, this function was named &lt;code&gt;init&lt;/code&gt; followed by the module name, hence:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;initsimp&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The initialization function creates the module object itself.&lt;/p&gt;
&lt;p&gt;Every function listed in the module&amp;rsquo;s method table becomes a method of that module.&lt;/p&gt;
&lt;p&gt;In our case:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; PyMethodDef SimpMethods[]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;contains:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the names visible from Python,&lt;/li&gt;
&lt;li&gt;the addresses of the corresponding C functions,&lt;/li&gt;
&lt;li&gt;additional flags describing how arguments are passed.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;METH_VARARGS&lt;/code&gt; flag indicates that Python will pass arguments as a tuple.&lt;/p&gt;
&lt;p&gt;The binding functions themselves follow a simple pattern:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Validate input arguments.&lt;/li&gt;
&lt;li&gt;Perform the actual computation.&lt;/li&gt;
&lt;li&gt;Convert the result into a Python object.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Argument validation is handled by:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;PyArg_ParseTuple&lt;/span&gt;(args, &lt;span style="color:#e6db74"&gt;&amp;#34;ii&amp;#34;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;x, &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;y)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The format string &lt;code&gt;&amp;quot;ii&amp;quot;&lt;/code&gt; means:&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;I expect two arguments, and both of them must be integers.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;If validation fails, the function should simply return &lt;code&gt;NULL&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Building the return value is similarly straightforward:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Py_BuildValue&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;i&amp;#34;&lt;/span&gt;, result);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;which constructs a Python integer object.&lt;/p&gt;
&lt;p&gt;The Python documentation traditionally recommends declaring all binding functions as &lt;code&gt;static&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="building-the-module"&gt;Building the Module
&lt;/h2&gt;&lt;p&gt;One way to build the extension is to use &lt;code&gt;distutils&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="example-setuppy"&gt;Example setup.py
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#!/usr/bin/env python3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;from&lt;/span&gt; distutils.core &lt;span style="color:#f92672"&gt;import&lt;/span&gt; setup, Extension
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;simpmodule &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Extension(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;simp&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sources&lt;span style="color:#f92672"&gt;=&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;&amp;#39;simpmodule.c&amp;#39;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; libraries&lt;span style="color:#f92672"&gt;=&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;&amp;#39;simp&amp;#39;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; library_dirs&lt;span style="color:#f92672"&gt;=&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;setup(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;SimpLib&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; version&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;1.0&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; description&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;This is SimpLib bindings package&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ext_modules&lt;span style="color:#f92672"&gt;=&lt;/span&gt;[simpmodule]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;Extension&lt;/code&gt; object describes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;source files,&lt;/li&gt;
&lt;li&gt;required libraries,&lt;/li&gt;
&lt;li&gt;library search paths.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;setup()&lt;/code&gt; function handles the rest.&lt;/p&gt;
&lt;h3 id="linux-2"&gt;Linux
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;python setup.py build
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="windows-2"&gt;Windows
&lt;/h3&gt;&lt;p&gt;Unfortunately, Python traditionally expects Visual C++ when building extension modules.&lt;/p&gt;
&lt;p&gt;If that doesn&amp;rsquo;t bother you, feel free to use it.&lt;/p&gt;
&lt;p&gt;That would, however, make this article considerably shorter.&lt;/p&gt;
&lt;p&gt;To force MinGW:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;python setup.py build --compiler&lt;span style="color:#f92672"&gt;=&lt;/span&gt;mingw32
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="installing-the-module"&gt;Installing the Module
&lt;/h2&gt;&lt;h3 id="linux-3"&gt;Linux
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;python setup.py install
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The extension and all required files will be installed into the appropriate Python directories.&lt;/p&gt;
&lt;h3 id="windows-3"&gt;Windows
&lt;/h3&gt;&lt;p&gt;The generated &lt;code&gt;simp.pyd&lt;/code&gt; file should be copied into either:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Lib\site-packages
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;or&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;%APPDATA%\Roaming\Python\site-packages
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Make sure you know which Python installation you&amp;rsquo;re targeting before copying files around.&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;If you happen to own Visual C++, and if the sight of it does not cause emotional distress, installation works exactly like it does on Linux.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="a-short-test-program"&gt;A Short Test Program
&lt;/h2&gt;&lt;p&gt;Naturally, the best way to test the module is to use it.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;from&lt;/span&gt; simp &lt;span style="color:#f92672"&gt;import&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(&lt;span style="color:#e6db74"&gt;&amp;#34;Adding 212 to 384:&amp;#34;&lt;/span&gt;, add2x(&lt;span style="color:#ae81ff"&gt;212&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;384&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(&lt;span style="color:#e6db74"&gt;&amp;#34;Multiplying 212 by 384:&amp;#34;&lt;/span&gt;, mul2x(&lt;span style="color:#ae81ff"&gt;212&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;384&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You should also verify that incorrect input is handled properly.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(mul2x(&lt;span style="color:#ae81ff"&gt;212&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;A tester walks into a bar&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;or:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(mul2x(&lt;span style="color:#ae81ff"&gt;212&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;384&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;25&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Both cases should result in Python exceptions being raised by the argument validation code.&lt;/p&gt;
&lt;h2 id="final-thoughts"&gt;Final Thoughts
&lt;/h2&gt;&lt;p&gt;Keep your spirits up.&lt;/p&gt;
&lt;p&gt;Rome wasn&amp;rsquo;t built in a day.&lt;/p&gt;
&lt;p&gt;Neither are C libraries, Python bindings, build systems, or debugging skills.&lt;/p&gt;
&lt;p&gt;Compilation errors, broken builds, failed tests, and nights spent chasing mysterious bugs are simply part of the profession.&lt;/p&gt;
&lt;p&gt;The important thing is to remember that every experienced developer has been through exactly the same process.&lt;/p&gt;
&lt;p&gt;Some of them are still going through it.&lt;/p&gt;</description></item></channel></rss>