Skip to content

cdll.LoadLibrary allows None as an argument #78773

Closed

Description

@superbobry
mannequin
BPO 34592
Nosy @gpshead, @vstinner, @superbobry, @mhsmith

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = None
closed_at = None
created_at = <Date 2018-09-05.21:35:41.405>
labels = ['3.11', 'invalid', 'docs']
title = 'cdll.LoadLibrary allows None as an argument'
updated_at = <Date 2021-11-19.04:06:58.621>
user = 'https://github.com/superbobry'

bugs.python.org fields:

activity = <Date 2021-11-19.04:06:58.621>
actor = 'gregory.p.smith'
assignee = 'docs@python'
closed = False
closed_date = None
closer = None
components = ['Documentation']
creation = <Date 2018-09-05.21:35:41.405>
creator = 'superbobry'
dependencies = []
files = []
hgrepos = []
issue_num = 34592
keywords = []
message_count = 5.0
messages = ['324654', '361734', '361735', '361807', '406570']
nosy_count = 5.0
nosy_names = ['gregory.p.smith', 'vstinner', 'docs@python', 'superbobry', 'Malcolm Smith']
pr_nums = []
priority = 'normal'
resolution = 'not a bug'
stage = 'needs patch'
status = 'open'
superseder = None
type = None
url = 'https://bugs.python.org/issue34592'
versions = ['Python 3.11']

Linked PRs

Activity

  1. superbobry commented on Sep 5, 2018

    superbobrymannequin
    MannequinAuthor

    LoadLibrary in Python 2.7 through 3.7 accepts None as an argument. I wonder if this has been allowed for a reason? If not, it should probably be changed to raise a TypeError instead.

    >>> ctypes.cdll.LoadLibrary(None)
    <CDLL 'None', handle fffffffffffffffe at 10eedbe90>

    Interestingly, on Python 2.7 LoadLibrary explicitly mentions None as allowed in the error message:

    >>> ctypes.cdll.LoadLibrary(42)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "[...]/ctypes/__init__.py", line 444, in LoadLibrary
        return self._dlltype(name)
      File "[...]/ctypes/__init__.py", line 366, in __init__
        self._handle = _dlopen(self._name, mode)
    TypeError: dlopen() argument 1 must be string or None, not int

    A side-effect of None being allowed is that chaining find_library and LoadLibrary is error-prone:

    >>> ctypes.cdll.LoadLibrary(find_library("foobar"))
    <CDLL 'None', handle fffffffffffffffe at 10ef35fd0>
  2. mhsmith commented on Feb 10, 2020

    mhsmithmannequin
    Mannequin

    This isn't documented, but CDLL(None) is translated to dlopen(NULL), which "causes a search for a symbol in the main program, followed by all shared libraries loaded at program startup, and then all shared libraries loaded by dlopen() with the flag RTLD_GLOBAL" (https://linux.die.net/man/3/dlopen).

    This is sometimes useful because it lets you look up a symbol in an already-loaded library without needing to give the library's name. For example:

    >>> import ctypes
    >>> dll = ctypes.CDLL(None)
    >>> dll.printf
    <_FuncPtr object at 0x7f3427d547c0>
    >>> dll.PyObject_Str
    <_FuncPtr object at 0x7f3427d54880>
  3. vstinner commented on Feb 10, 2020

    @vstinner
    Member

    I'm using LoadLibrary(None) commonly to load symbols in Python itself ;-)

  4. vstinner commented on Feb 11, 2020

    @vstinner
    Member

    In clear, it's a feature, not a bug.

  5. gpshead commented on Nov 19, 2021

    @gpshead
    Member

    We do need to document this in ctypes.rst. Quite a bit of code depends on ctypes.CDLL(None) and similar to get at symbols linked into the interpreter or already dlopened into the process these days. It works on Linux; I'm assuming it likely does on everything POSIXy.

  6. added
    docsDocumentation in the Doc dir
    3.11only security fixes
    and removed on Nov 19, 2021
  7. transferred this issue fromon Apr 10, 2022
  8. encukou commented on Feb 4, 2025

    @encukou
    Member

    I'm assuming it likely does on everything POSIXy.

    Indeed. POSIX says:

    If file is a null pointer, dlopen() shall return a global symbol table handle for the currently running process image. This symbol table handle shall provide access to the symbols from an ordered set of executable object files consisting of the original program image file, any executable object files loaded at program start-up as specified by that process file (for example, shared libraries), and the set of executable object files loaded using dlopen() operations with the RTLD_GLOBAL flag. As the latter set of executable object files can change during execution, the set of symbols made available by this symbol table handle can also change dynamically.

  9. added 2 commits that reference this issue on Feb 27, 2026
  10. added a commit that references this issue on Mar 9, 2026
  11. added a commit that references this issue on Mar 9, 2026
  12. added a commit that references this issue on Mar 9, 2026
  13. encukou commented on Mar 9, 2026

    @encukou
    Member

    Docs are now in.

  14. added a commit that references this issue on Apr 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.11only security fixesdocsDocumentation in the Doc dirtopic-ctypes

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions