Move Stable ABI to more sensible section and update html sectioning

This commit is contained in:
William S Fulton 2024-03-20 22:59:49 +00:00
parent 639a76fe12
commit 2a02238883
3 changed files with 96 additions and 89 deletions

View File

@ -465,6 +465,10 @@
<li><a href="Library.html#Library_shared_ptr_directors">shared_ptr and directors</a>
</ul>
<li><a href="Library.html#Library_std_unique_ptr">unique_ptr smart pointer</a>
<ul>
<li><a href="Library.html#Library_std_unique_ptr_by_value">unique_ptr passed by value</a>
<li><a href="Library.html#Library_std_unique_ptr_by_ref">unique_ptr passed by reference</a>
</ul>
<li><a href="Library.html#Library_std_auto_ptr">auto_ptr smart pointer</a>
</ul>
<li><a href="Library.html#Library_nn16">Utility Libraries</a>
@ -1451,7 +1455,6 @@
<li><a href="Python.html#Python_nn37">Overhead and code bloat</a>
<li><a href="Python.html#Python_nn38">Typemaps</a>
<li><a href="Python.html#Python_nn39">Miscellaneous</a>
<li><a href="Python.html#Python_stable_abi">Stable ABI</a>
</ul>
<li><a href="Python.html#Python_nn40">Common customization features</a>
<ul>
@ -1463,6 +1466,7 @@
<ul>
<li><a href="Python.html#Python_fastproxy">-fastproxy</a>
</ul>
<li><a href="Python.html#Python_stable_abi">Stable ABI</a>
</ul>
<li><a href="Python.html#Python_nn45">Tips and techniques</a>
<ul>

View File

@ -42,6 +42,10 @@
<li><a href="#Library_shared_ptr_directors">shared_ptr and directors</a>
</ul>
<li><a href="#Library_std_unique_ptr">unique_ptr smart pointer</a>
<ul>
<li><a href="#Library_std_unique_ptr_by_value">unique_ptr passed by value</a>
<li><a href="#Library_std_unique_ptr_by_ref">unique_ptr passed by reference</a>
</ul>
<li><a href="#Library_std_auto_ptr">auto_ptr smart pointer</a>
</ul>
<li><a href="#Library_nn16">Utility Libraries</a>
@ -2107,7 +2111,8 @@ The ownership and move semantics described here can of course be modified if not
by copying and customising the typemaps in the appropriate <tt>std_unique_ptr.i</tt> library file.
</p>
<H4><a name="Library_std_unique_ptr_by_value">12.4.6 unique_ptr passed by value</a></H4>
<H4><a name="Library_std_unique_ptr_by_value">12.4.6.1 unique_ptr passed by value</a></H4>
<p>
Example usage of a <tt>std::unique_ptr</tt> being returned from a function by value is shown below.
@ -2214,7 +2219,8 @@ Attempts to pass ownership from a proxy class to a <tt>std::unique</tt> paramete
in a "Cannot release ownership as memory is not owned" exception. For example, if <tt>example.take(k)</tt> in the example above is called twice.
</p>
<H4><a name="Library_std_unique_ptr_by_ref">12.4.6 unique_ptr passed by reference</a></H4>
<H4><a name="Library_std_unique_ptr_by_ref">12.4.6.2 unique_ptr passed by reference</a></H4>
<p>
The effect of passing a <tt>std::unique_ptr</tt> by rvalue reference into a function is identical to passing it by value.

View File

@ -3,7 +3,7 @@
<head>
<title>SWIG and Python</title>
<link rel="stylesheet" type="text/css" href="style.css">
<meta http-equiv="Content-type" content="text/html; charset=utf-8" /><meta charset="UTF-8" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body bgcolor="#ffffff">
@ -65,7 +65,6 @@
<li><a href="#Python_nn37">Overhead and code bloat</a>
<li><a href="#Python_nn38">Typemaps</a>
<li><a href="#Python_nn39">Miscellaneous</a>
<li><a href="#Python_stable_abi">Stable ABI</a>
</ul>
<li><a href="#Python_nn40">Common customization features</a>
<ul>
@ -77,6 +76,7 @@
<ul>
<li><a href="#Python_fastproxy">-fastproxy</a>
</ul>
<li><a href="#Python_stable_abi">Stable ABI</a>
</ul>
<li><a href="#Python_nn45">Tips and techniques</a>
<ul>
@ -3319,90 +3319,6 @@ director feature for reentrant, recursive or threaded member
methods that return const references.
</p>
<H3><a name="Python_stable_abi">33.5.8 Stable ABI</a></H3>
<p>
By default, the version of Python used to compile the wrappers needs to be the same as that used during runtime.
Alternatvely, the <a href="https://docs.python.org/3/c-api/stable.html">Python Stable ABI</a> enables a single compiled binary to be used by different versions of Python.
This is enabled by defining <tt>Py_LIMITED_API</tt> during the compilation of the C/C++ wrapper code and setting this macro to a particular minimum version of Python that one wants to support.
</p>
<p>
SWIG supports the stable ABI, but only version 3.4 of Python and later is supported.
There are two recommended approaches for using SWIG and the stable ABI and both require setting the <tt>Py_LIMITED_API</tt> macro to be set to <tt>0x03040000</tt> as a minimum value (Python 3.4).
Either set this using <tt>%begin</tt> by adding the following into your interface file so that this macro appears at the beginning of the generated C/C++ code:
</p>
<div class="code"><pre>
%begin %{
#define Py_LIMITED_API 0x03040000
%}
</pre></div>
<p>
or simply define the macro using your C/C++ compiler's <tt>-D</tt> command line option, for example, <tt>-DPy_LIMITED_API=0x03040000</tt>.
</p>
<p>
The default SWIG command line options generate code that enable the limited API/stable ABI.
Some options, such as <tt>-builtin</tt>, <tt>-fast</tt> (used by <tt>-O</tt>) do not use the limited API and hence when <tt>Py_LIMITED_API</tt> is defined there will be missing symbols during compilation.
Compatibility of user's custom typemaps is of course dependent on the Python APIs used in the typemaps.
</p>
<p>
As discussed in the official <a href="https://docs.python.org/3/c-api/stable.html">Python Stable ABI</a> documentation, there is no guarantee that code conforms to the Limited API or Stable ABI when defining <tt>Py_LIMITED_API</tt>.
There are a number of recommendations and caveats detailed there which are worth studying.
The Stable ABI is also evolving and being modified with each Python release.
In fact there is a Python C API working group, <a href="https://github.com/capi-workgroup/">capi-workgroup</a>, which was setup in the first half of 2023.
The <a href="https://github.com/capi-workgroup/problems/issues">capi-workgroup/problems issues</a> is very enlightening reading for anyone using the Stable ABI.
<a href="https://peps.python.org/pep-0733/">PEP 733</a> came out of the working group and is an evaluation of Python's C API.
</p>
<p>
There is a lot of information to digest in this space, but a simple approach would be to follow the offical recommendation of testing an extension with all minor Python versions you want to support,
and to build with the lowest supported version.
SWIG supports at least Python 3.4 for the Stable ABI so this would be a good version to compile a SWIG extension against.
There is also a useful tool <a href="https://github.com/trailofbits/abi3audit/">abi3audit</a> which can be used to check the compiled extension for Stable ABI conformance.
It can be easily installed with pip and then used to check a SWIG generated shared object or wheel even.
Note that if you are using it to check a shared object, the shared object must be renamed to have abi3 in the name.
For example, below is the output on Linux for the class example shipped with SWIG, if <tt>Py_LIMITED_API</tt> is set as described earlier:
</p>
<div class="shell">
<pre>
~/swig/Examples/python/class $ mv _example.so _example.abi3.so
~/swig/Examples/python/class $ abi3audit --verbose --assume-minimum-abi3 3.4 _example.abi3.so
[22:12:18] WARNING no wheel to infer abi3 version from; assuming (3.4)
[22:12:18] 💁 _example.abi3.so: 1 extensions scanned; 0 ABI version mismatches and 0 ABI violations found
</pre>
</div>
<p>
If <tt>Py_LIMITED_API</tt> is not set, the check fails, but this should be expected:
</p>
<div class="shell">
<pre>
~/swig/Examples/python/class $ mv _example.so _example.abi3.so
~/swig/Examples/python/class $ abi3audit --verbose --assume-minimum-abi3 3.4 _example.abi3.so
abi3audit --verbose --assume-minimum-abi3 3.4 _example.abi3.so
[22:22:27] WARNING no wheel to infer abi3 version from; assuming (3.4)
[22:22:27] 👎 : _example.abi3.so uses the Python 3.10 ABI, but is tagged for the Python 3.4 ABI
┏━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┓
┃ Symbol ┃ Version ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━┩
│ PyUnicode_AsUTF8AndSize │ 3.10 │
└─────────────────────────┴─────────┘
💁 _example.abi3.so: 1 extensions scanned; 1 ABI version mismatches and 0 ABI violations found
</pre>
</div>
<p>
<b>Compatibility Note:</b> Support for the stable ABI was added in SWIG-4.2.0.
</p>
<H2><a name="Python_nn40">33.6 Common customization features</a></H2>
@ -4119,6 +4035,87 @@ While this possibly provides the best of both worlds, the time to import the mod
The command line options mentioned above also apply to wrapped C/C++ global functions, not just class methods.
</p>
<H3><a name="Python_stable_abi">33.6.6 Stable ABI</a></H3>
<p>
By default, the version of Python used to compile the wrappers needs to be the same as that used during runtime.
Alternatvely, the <a href="https://docs.python.org/3/c-api/stable.html">Python Stable ABI</a> enables a single compiled binary to be used by different versions of Python.
This is enabled by defining <tt>Py_LIMITED_API</tt> during the compilation of the C/C++ wrapper code and setting this macro to a particular minimum version of Python that one wants to support.
</p>
<p>
SWIG supports the stable ABI, but only version 3.4 of Python and later is supported.
There are two recommended approaches for using SWIG and the stable ABI and both require setting the <tt>Py_LIMITED_API</tt> macro to be set to <tt>0x03040000</tt> as a minimum value (Python 3.4).
Either set this using <tt>%begin</tt> by adding the following into your interface file so that this macro appears at the beginning of the generated C/C++ code:
</p>
<div class="code"><pre>
%begin %{
#define Py_LIMITED_API 0x03040000
%}
</pre></div>
<p>
or simply define the macro using your C/C++ compiler's <tt>-D</tt> command line option, for example, <tt>-DPy_LIMITED_API=0x03040000</tt>.
</p>
<p>
The default SWIG command line options generate code that enable the limited API/stable ABI.
Some options, such as <tt>-builtin</tt>, <tt>-fast</tt> (used by <tt>-O</tt>) do not use the limited API and hence when <tt>Py_LIMITED_API</tt> is defined there will be missing symbols during compilation.
Compatibility of user's custom typemaps is of course dependent on the Python APIs used in the typemaps.
</p>
<p>
As discussed in the official <a href="https://docs.python.org/3/c-api/stable.html">Python Stable ABI</a> documentation, there is no guarantee that code conforms to the Limited API or Stable ABI when defining <tt>Py_LIMITED_API</tt>.
There are a number of recommendations and caveats detailed there which are worth studying.
The Stable ABI is also evolving and being modified with each Python release.
In fact there is a Python C API working group, <a href="https://github.com/capi-workgroup/">capi-workgroup</a>, which was setup in the first half of 2023.
The <a href="https://github.com/capi-workgroup/problems/issues">capi-workgroup/problems issues</a> is very enlightening reading for anyone using the Stable ABI.
<a href="https://peps.python.org/pep-0733/">PEP 733</a> came out of the working group and is an evaluation of Python's C API.
</p>
<p>
There is a lot of information to digest in this space, but a simple approach would be to follow the offical recommendation of testing an extension with all minor Python versions you want to support,
and to build with the lowest supported version.
SWIG supports at least Python 3.4 for the Stable ABI so this would be a good version to compile a SWIG extension against.
There is also a useful tool <a href="https://github.com/trailofbits/abi3audit/">abi3audit</a> which can be used to check the compiled extension for Stable ABI conformance.
It can be easily installed with pip and then used to check a SWIG generated shared object or wheel even.
Note that if you are using it to check a shared object, the shared object must be renamed to have abi3 in the name.
For example, below is the output on Linux for the class example shipped with SWIG, if <tt>Py_LIMITED_API</tt> is set as described earlier:
</p>
<div class="shell">
<pre>
~/swig/Examples/python/class $ mv _example.so _example.abi3.so
~/swig/Examples/python/class $ abi3audit --assume-minimum-abi3 3.4 _example.abi3.so
[22:12:18] WARNING no wheel to infer abi3 version from; assuming (3.4)
[22:12:18] _example.abi3.so: 1 extensions scanned; 0 ABI version mismatches and 0 ABI violations found
</pre>
</div>
<p>
If <tt>Py_LIMITED_API</tt> is not set, the check fails, but this should be expected:
</p>
<div class="shell">
<pre>
~/swig/Examples/python/class $ mv _example.so _example.abi3.so
~/swig/Examples/python/class $ abi3audit --report --assume-minimum-abi3 3.4 _example.abi3.so
[22:22:27] WARNING no wheel to infer abi3 version from; assuming (3.4)
[22:22:27] _example.abi3.so: 1 extensions scanned; 1 ABI version mismatches and 0 ABI violations found
{"specs": {"_example.abi3.so": {"kind": "object", "object": {"name": "_example.abi3.so",
"result": {"is_abi3": true, "is_abi3_baseline_compatible": false, "baseline": "3.4", "computed": "3.10",
"non_abi3_symbols": [], "future_abi3_objects": {"PyUnicode_AsUTF8AndSize": "3.10"}}}}}}
</pre>
</div>
<p>
<b>Compatibility Note:</b> Support for the stable ABI was added in SWIG-4.2.0.
</p>
<H2><a name="Python_nn45">33.7 Tips and techniques</a></H2>