Skip to content

Commit 778ff23

Browse files
[3.14] gh-78773: Improve ctypes dynamic library loading docs (GH-145313) (GH-145674)
(cherry picked from commit d64f83d) Co-authored-by: Petr Viktorin <encukou@gmail.com>
1 parent b194688 commit 778ff23

File tree

1 file changed

+133
-117
lines changed

1 file changed

+133
-117
lines changed

Doc/library/ctypes.rst

Lines changed: 133 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,6 @@ used to wrap these libraries in pure Python.
2222
ctypes tutorial
2323
---------------
2424

25-
Note: The code samples in this tutorial use :mod:`doctest` to make sure that
26-
they actually work. Since some code samples behave differently under Linux,
27-
Windows, or macOS, they contain doctest directives in comments.
28-
2925
Note: Some code samples reference the ctypes :class:`c_int` type. On platforms
3026
where ``sizeof(long) == sizeof(int)`` it is an alias to :class:`c_long`.
3127
So, you should not be confused if :class:`c_long` is printed if you would expect
@@ -36,13 +32,16 @@ So, you should not be confused if :class:`c_long` is printed if you would expect
3632
Loading dynamic link libraries
3733
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3834

39-
:mod:`!ctypes` exports the *cdll*, and on Windows *windll* and *oledll*
35+
:mod:`!ctypes` exports the :py:data:`~ctypes.cdll`, and on Windows
36+
:py:data:`~ctypes.windll` and :py:data:`~ctypes.oledll`
4037
objects, for loading dynamic link libraries.
4138

42-
You load libraries by accessing them as attributes of these objects. *cdll*
43-
loads libraries which export functions using the standard ``cdecl`` calling
44-
convention, while *windll* libraries call functions using the ``stdcall``
45-
calling convention. *oledll* also uses the ``stdcall`` calling convention, and
39+
You load libraries by accessing them as attributes of these objects.
40+
:py:data:`!cdll` loads libraries which export functions using the
41+
standard ``cdecl`` calling convention, while :py:data:`!windll`
42+
libraries call functions using the ``stdcall``
43+
calling convention.
44+
:py:data:`~oledll` also uses the ``stdcall`` calling convention, and
4645
assumes the functions return a Windows :c:type:`!HRESULT` error code. The error
4746
code is used to automatically raise an :class:`OSError` exception when the
4847
function call fails.
@@ -72,11 +71,13 @@ Windows appends the usual ``.dll`` file suffix automatically.
7271
being used by Python. Where possible, use native Python functionality,
7372
or else import and use the ``msvcrt`` module.
7473

75-
On Linux, it is required to specify the filename *including* the extension to
74+
Other systems require the filename *including* the extension to
7675
load a library, so attribute access can not be used to load libraries. Either the
7776
:meth:`~LibraryLoader.LoadLibrary` method of the dll loaders should be used,
78-
or you should load the library by creating an instance of CDLL by calling
79-
the constructor::
77+
or you should load the library by creating an instance of :py:class:`CDLL`
78+
by calling the constructor.
79+
80+
For example, on Linux::
8081

8182
>>> cdll.LoadLibrary("libc.so.6") # doctest: +LINUX
8283
<CDLL 'libc.so.6', handle ... at ...>
@@ -85,7 +86,14 @@ the constructor::
8586
<CDLL 'libc.so.6', handle ... at ...>
8687
>>>
8788

88-
.. XXX Add section for macOS.
89+
On macOS::
90+
91+
>>> cdll.LoadLibrary("libc.dylib") # doctest: +MACOS
92+
<CDLL 'libc.dylib', handle ... at ...>
93+
>>> libc = CDLL("libc.dylib") # doctest: +MACOS
94+
>>> libc # doctest: +MACOS
95+
<CDLL 'libc.dylib', handle ... at ...>
96+
8997

9098

9199
.. _ctypes-accessing-functions-from-loaded-dlls:
@@ -1458,14 +1466,82 @@ Loading shared libraries
14581466
^^^^^^^^^^^^^^^^^^^^^^^^
14591467

14601468
There are several ways to load shared libraries into the Python process. One
1461-
way is to instantiate one of the following classes:
1469+
way is to instantiate :py:class:`CDLL` or one of its subclasses:
14621470

14631471

14641472
.. class:: CDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None)
14651473

1466-
Instances of this class represent loaded shared libraries. Functions in these
1467-
libraries use the standard C calling convention, and are assumed to return
1468-
:c:expr:`int`.
1474+
Represents a loaded shared library.
1475+
1476+
Functions in this library use the standard C calling convention, and are
1477+
assumed to return :c:expr:`int`.
1478+
The Python :term:`global interpreter lock` is released before calling any
1479+
function exported by these libraries, and reacquired afterwards.
1480+
For different function behavior, use a subclass: :py:class:`~ctypes.OleDLL`,
1481+
:py:class:`~ctypes.WinDLL`, or :py:class:`~ctypes.PyDLL`.
1482+
1483+
If you have an existing :py:attr:`handle <ctypes.CDLL._handle>` to an already
1484+
loaded shared library, it can be passed as the *handle* argument to wrap
1485+
the opened library in a new :py:class:`!CDLL` object.
1486+
In this case, *name* is only used to set the :py:attr:`~ctypes.CDLL._name`
1487+
attribute, but it may be adjusted and/or validated.
1488+
1489+
If *handle* is ``None``, the underlying platform's :manpage:`dlopen(3)` or
1490+
:c:func:`!LoadLibrary` function is used to load the library into
1491+
the process, and to get a handle to it.
1492+
1493+
*name* is the pathname of the shared library to open.
1494+
If *name* does not contain a path separator, the library is found
1495+
in a platform-specific way.
1496+
1497+
On non-Windows systems, *name* can be ``None``. In this case,
1498+
:c:func:`!dlopen` is called with ``NULL``, which opens the main program
1499+
as a "library".
1500+
(Some systems do the same is *name* is empty; ``None``/``NULL`` is more
1501+
portable.)
1502+
1503+
.. admonition:: CPython implementation detail
1504+
1505+
Since CPython is linked to ``libc``, a ``None`` *name* is often used
1506+
to access the C standard library::
1507+
1508+
>>> printf = ctypes.CDLL(None).printf
1509+
>>> printf.argtypes = [ctypes.c_char_p]
1510+
>>> printf(b"hello\n")
1511+
hello
1512+
6
1513+
1514+
To access the Python C API, prefer :py:data:`ctypes.pythonapi` which
1515+
works across platforms.
1516+
1517+
The *mode* parameter can be used to specify how the library is loaded. For
1518+
details, consult the :manpage:`dlopen(3)` manpage. On Windows, *mode* is
1519+
ignored. On posix systems, RTLD_NOW is always added, and is not
1520+
configurable.
1521+
1522+
The *use_errno* parameter, when set to true, enables a ctypes mechanism that
1523+
allows accessing the system :data:`errno` error number in a safe way.
1524+
:mod:`!ctypes` maintains a thread-local copy of the system's :data:`errno`
1525+
variable; if you call foreign functions created with ``use_errno=True`` then the
1526+
:data:`errno` value before the function call is swapped with the ctypes private
1527+
copy, the same happens immediately after the function call.
1528+
1529+
The function :func:`ctypes.get_errno` returns the value of the ctypes private
1530+
copy, and the function :func:`ctypes.set_errno` changes the ctypes private copy
1531+
to a new value and returns the former value.
1532+
1533+
The *use_last_error* parameter, when set to true, enables the same mechanism for
1534+
the Windows error code which is managed by the :func:`GetLastError` and
1535+
:func:`!SetLastError` Windows API functions; :func:`ctypes.get_last_error` and
1536+
:func:`ctypes.set_last_error` are used to request and change the ctypes private
1537+
copy of the windows error code.
1538+
1539+
The *winmode* parameter is used on Windows to specify how the library is loaded
1540+
(since *mode* is ignored). It takes any value that is valid for the Win32 API
1541+
``LoadLibraryEx`` flags parameter. When omitted, the default is to use the
1542+
flags that result in the most secure DLL load, which avoids issues such as DLL
1543+
hijacking. Passing the full path to the DLL is the safest way to ensure the
1544+
correct library and dependencies are loaded.
14691545

14701546
On Windows creating a :class:`CDLL` instance may fail even if the DLL name
14711547
exists. When a dependent DLL of the loaded DLL is not found, a
@@ -1477,20 +1553,47 @@ way is to instantiate one of the following classes:
14771553
DLLs and determine which one is not found using Windows debugging and
14781554
tracing tools.
14791555

1556+
.. seealso::
1557+
1558+
`Microsoft DUMPBIN tool <https://learn.microsoft.com/en-us/cpp/build/reference/dumpbin-reference?view=msvc-170>`_
1559+
-- A tool to find DLL dependents.
1560+
1561+
.. versionchanged:: 3.8
1562+
Added *winmode* parameter.
1563+
14801564
.. versionchanged:: 3.12
14811565

14821566
The *name* parameter can now be a :term:`path-like object`.
14831567

1484-
.. seealso::
1568+
Instances of this class have no public methods. Functions exported by the
1569+
shared library can be accessed as attributes or by index. Please note that
1570+
accessing the function through an attribute caches the result and therefore
1571+
accessing it repeatedly returns the same object each time. On the other hand,
1572+
accessing it through an index returns a new object each time::
1573+
1574+
>>> from ctypes import CDLL
1575+
>>> libc = CDLL("libc.so.6") # On Linux
1576+
>>> libc.time == libc.time
1577+
True
1578+
>>> libc['time'] == libc['time']
1579+
False
1580+
1581+
The following public attributes are available. Their name starts with an
1582+
underscore to not clash with exported function names:
1583+
1584+
.. attribute:: _handle
1585+
1586+
The system handle used to access the library.
14851587

1486-
`Microsoft DUMPBIN tool <https://docs.microsoft.com/cpp/build/reference/dependents>`_
1487-
-- A tool to find DLL dependents.
1588+
.. attribute:: _name
14881589

1590+
The name of the library passed in the constructor.
14891591

1490-
.. class:: OleDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None)
1592+
.. class:: OleDLL
14911593

1492-
Instances of this class represent loaded shared libraries,
1493-
functions in these libraries use the ``stdcall`` calling convention, and are
1594+
See :py:class:`~ctypes.CDLL`, the superclass, for common information.
1595+
1596+
Functions in this library use the ``stdcall`` calling convention, and are
14941597
assumed to return the windows specific :class:`HRESULT` code. :class:`HRESULT`
14951598
values contain information specifying whether the function call failed or
14961599
succeeded, together with additional error code. If the return value signals a
@@ -1502,133 +1605,51 @@ way is to instantiate one of the following classes:
15021605
:exc:`WindowsError` used to be raised,
15031606
which is now an alias of :exc:`OSError`.
15041607

1505-
.. versionchanged:: 3.12
1506-
1507-
The *name* parameter can now be a :term:`path-like object`.
15081608

1609+
.. class:: WinDLL
15091610

1510-
.. class:: WinDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None)
1611+
See :py:class:`~ctypes.CDLL`, the superclass, for common information.
15111612

1512-
Instances of this class represent loaded shared libraries,
1513-
functions in these libraries use the ``stdcall`` calling convention, and are
1613+
Functions in these libraries use the ``stdcall`` calling convention, and are
15141614
assumed to return :c:expr:`int` by default.
15151615

15161616
.. availability:: Windows
15171617

1518-
.. versionchanged:: 3.12
1618+
.. class:: PyDLL
15191619

1520-
The *name* parameter can now be a :term:`path-like object`.
1620+
See :py:class:`~ctypes.CDLL`, the superclass, for common information.
15211621

1522-
1523-
The Python :term:`global interpreter lock` is released before calling any
1524-
function exported by these libraries, and reacquired afterwards.
1525-
1526-
1527-
.. class:: PyDLL(name, mode=DEFAULT_MODE, handle=None)
1528-
1529-
Instances of this class behave like :class:`CDLL` instances, except that the
1622+
When functions in this library are called, the
15301623
Python GIL is *not* released during the function call, and after the function
15311624
execution the Python error flag is checked. If the error flag is set, a Python
15321625
exception is raised.
15331626

1534-
Thus, this is only useful to call Python C api functions directly.
1535-
1536-
.. versionchanged:: 3.12
1537-
1538-
The *name* parameter can now be a :term:`path-like object`.
1539-
1540-
All these classes can be instantiated by calling them with at least one
1541-
argument, the pathname of the shared library. If you have an existing handle to
1542-
an already loaded shared library, it can be passed as the ``handle`` named
1543-
parameter, otherwise the underlying platform's :c:func:`!dlopen` or
1544-
:c:func:`!LoadLibrary` function is used to load the library into
1545-
the process, and to get a handle to it.
1546-
1547-
The *mode* parameter can be used to specify how the library is loaded. For
1548-
details, consult the :manpage:`dlopen(3)` manpage. On Windows, *mode* is
1549-
ignored. On posix systems, RTLD_NOW is always added, and is not
1550-
configurable.
1551-
1552-
The *use_errno* parameter, when set to true, enables a ctypes mechanism that
1553-
allows accessing the system :data:`errno` error number in a safe way.
1554-
:mod:`!ctypes` maintains a thread-local copy of the system's :data:`errno`
1555-
variable; if you call foreign functions created with ``use_errno=True`` then the
1556-
:data:`errno` value before the function call is swapped with the ctypes private
1557-
copy, the same happens immediately after the function call.
1558-
1559-
The function :func:`ctypes.get_errno` returns the value of the ctypes private
1560-
copy, and the function :func:`ctypes.set_errno` changes the ctypes private copy
1561-
to a new value and returns the former value.
1562-
1563-
The *use_last_error* parameter, when set to true, enables the same mechanism for
1564-
the Windows error code which is managed by the :func:`GetLastError` and
1565-
:func:`!SetLastError` Windows API functions; :func:`ctypes.get_last_error` and
1566-
:func:`ctypes.set_last_error` are used to request and change the ctypes private
1567-
copy of the windows error code.
1568-
1569-
The *winmode* parameter is used on Windows to specify how the library is loaded
1570-
(since *mode* is ignored). It takes any value that is valid for the Win32 API
1571-
``LoadLibraryEx`` flags parameter. When omitted, the default is to use the
1572-
flags that result in the most secure DLL load, which avoids issues such as DLL
1573-
hijacking. Passing the full path to the DLL is the safest way to ensure the
1574-
correct library and dependencies are loaded.
1575-
1576-
.. versionchanged:: 3.8
1577-
Added *winmode* parameter.
1627+
Thus, this is only useful to call Python C API functions directly.
15781628

15791629

15801630
.. data:: RTLD_GLOBAL
1581-
:noindex:
15821631

15831632
Flag to use as *mode* parameter. On platforms where this flag is not available,
15841633
it is defined as the integer zero.
15851634

15861635

15871636
.. data:: RTLD_LOCAL
1588-
:noindex:
15891637

15901638
Flag to use as *mode* parameter. On platforms where this is not available, it
15911639
is the same as *RTLD_GLOBAL*.
15921640

15931641

15941642
.. data:: DEFAULT_MODE
1595-
:noindex:
15961643

15971644
The default mode which is used to load shared libraries. On OSX 10.3, this is
15981645
*RTLD_GLOBAL*, otherwise it is the same as *RTLD_LOCAL*.
15991646

1600-
Instances of these classes have no public methods. Functions exported by the
1601-
shared library can be accessed as attributes or by index. Please note that
1602-
accessing the function through an attribute caches the result and therefore
1603-
accessing it repeatedly returns the same object each time. On the other hand,
1604-
accessing it through an index returns a new object each time::
1605-
1606-
>>> from ctypes import CDLL
1607-
>>> libc = CDLL("libc.so.6") # On Linux
1608-
>>> libc.time == libc.time
1609-
True
1610-
>>> libc['time'] == libc['time']
1611-
False
1612-
1613-
The following public attributes are available, their name starts with an
1614-
underscore to not clash with exported function names:
1615-
1616-
1617-
.. attribute:: PyDLL._handle
1618-
1619-
The system handle used to access the library.
1620-
1621-
1622-
.. attribute:: PyDLL._name
1623-
1624-
The name of the library passed in the constructor.
16251647

16261648
Shared libraries can also be loaded by using one of the prefabricated objects,
16271649
which are instances of the :class:`LibraryLoader` class, either by calling the
16281650
:meth:`~LibraryLoader.LoadLibrary` method, or by retrieving the library as
16291651
attribute of the loader instance.
16301652

1631-
16321653
.. class:: LibraryLoader(dlltype)
16331654

16341655
Class which loads shared libraries. *dlltype* should be one of the
@@ -1647,29 +1668,25 @@ attribute of the loader instance.
16471668
These prefabricated library loaders are available:
16481669

16491670
.. data:: cdll
1650-
:noindex:
16511671

16521672
Creates :class:`CDLL` instances.
16531673

16541674

16551675
.. data:: windll
1656-
:noindex:
16571676

16581677
Creates :class:`WinDLL` instances.
16591678

16601679
.. availability:: Windows
16611680

16621681

16631682
.. data:: oledll
1664-
:noindex:
16651683

16661684
Creates :class:`OleDLL` instances.
16671685

16681686
.. availability:: Windows
16691687

16701688

16711689
.. data:: pydll
1672-
:noindex:
16731690

16741691
Creates :class:`PyDLL` instances.
16751692

@@ -1678,7 +1695,6 @@ For accessing the C Python api directly, a ready-to-use Python shared library
16781695
object is available:
16791696

16801697
.. data:: pythonapi
1681-
:noindex:
16821698

16831699
An instance of :class:`PyDLL` that exposes Python C API functions as
16841700
attributes. Note that all these functions are assumed to return C

0 commit comments

Comments
 (0)