This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: cdll.LoadLibrary allows None as an argument
Type: Stage: needs patch
Components: Documentation Versions: Python 3.11
process
Status: open Resolution: not a bug
Dependencies: Superseder:
Assigned To: docs@python Nosy List: Malcolm Smith, docs@python, gregory.p.smith, superbobry, vstinner
Priority: normal Keywords:

Created on 2018-09-05 21:35 by superbobry, last changed 2022-04-11 14:59 by admin.

Messages (5)
msg324654 - (view) Author: Sergei Lebedev (superbobry) * Date: 2018-09-05 21:35
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>
msg361734 - (view) Author: Malcolm Smith (Malcolm Smith) Date: 2020-02-10 22:25
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>
msg361735 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2020-02-10 22:27
I'm using LoadLibrary(None) commonly to load symbols in Python itself ;-)
msg361807 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2020-02-11 12:25
In clear, it's a feature, not a bug.
msg406570 - (view) Author: Gregory P. Smith (gregory.p.smith) * (Python committer) Date: 2021-11-19 04:06
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.
History
Date User Action Args
2022-04-11 14:59:05adminsetgithub: 78773
2021-11-19 04:06:58gregory.p.smithsetstatus: closed -> open

assignee: docs@python
components: + Documentation
versions: + Python 3.11, - Python 2.7, Python 3.4, Python 3.5, Python 3.6, Python 3.7
nosy: + gregory.p.smith, docs@python

messages: + msg406570
stage: resolved -> needs patch
2020-02-11 12:25:18vstinnersetstatus: open -> closed
resolution: not a bug
messages: + msg361807

stage: resolved
2020-02-10 22:27:11vstinnersetnosy: + vstinner
messages: + msg361735
2020-02-10 22:25:02Malcolm Smithsetnosy: + Malcolm Smith
messages: + msg361734
2018-09-05 21:35:41superbobrycreate