Can someone explain to me why the following Python code works?
import ctypes
import ctypes.util
boblib = ctypes.cdll.LoadLibrary(ctypes.util.find_library("bob_is_your_uncle"))
boblib.cos.argtypes = [ctypes.c_double]
boblib.cos.restype = ctypes.c_double
print(boblib.cos(0)) # This prints out "1.0"
I am 1000% sure that there is no "bob_is_your_uncle" library on my filesystem. Yet, it seems like ctypes loads the m
library. Why is this happening?
Also, if I do this: print(boblib)
, I get this:
<CDLL 'None', handle 7f6a80f6d170 at 0x7f6a7f34d0b8>
What does CDLL 'None'
mean?
Thanks in advance.
PS: Doing a --version
on both my Python interpreters I get: Python 3.6.5rc1
and Python 2.7.14+
. The above code gives the same result on both versions. My OS is Debian (Testing repo).
It's not loading the math library. It appears to be loading the Python executable itself, which has cos
linked in.
There is indeed no library named bob_is_your_uncle
, so find_library
returns None
. (That's where the None
comes from in the output you're seeing.)
On Unix, the LoadLibrary
logic has a specific check that translates a None
name to a null pointer for the underlying dlopen
routine. dlopen
has special handling for a null name:
If filename is NULL, then the returned handle is for the main program.
In fact, on Unix, ctypes.pythonapi
is created as
pythonapi = PyDLL(None)
explaining why the None
handling is there in the first place. The CDLL object you've created is almost like ctypes.pythonapi
, except that it doesn't hold the GIL for function calls or check for exceptions (because CDLL instead of PyDLL), so it's useless for interacting with the actual C Python API.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments