python / cpython

The Python programming language
https://www.python.org
Other
62.74k stars 30.07k forks source link

`ctypes._FuncPtr` doesn't seem to exist as described in the doc (misspelled `_CFuncType`?) #120313

Open vmonteco opened 3 months ago

vmonteco commented 3 months ago

Documentation

Module ctypes doesn't seem to provide _FuncPtr when imported.

However, it provides _CFuncType that really looks similar to _FuncPtr as described by the documentation according to help().

Help on class CFuncPtr in module _ctypes:

class CFuncPtr(_CData)
 |  Function Pointer
 |
 |  Method resolution order:
 |      CFuncPtr
 |      _CData
 |      builtins.object
 |
 |  Methods defined here:
 |
 |  __bool__(self, /)
 |      True if self else False
 |
 |  __buffer__(self, flags, /)
 |      Return a buffer object that exposes the underlying memory of the object.
 |
 |  __call__(self, /, *args, **kwargs)
 |      Call self as a function.
 |
 |  __repr__(self, /)
 |      Return repr(self).
 |
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |
 |  __new__(*args, **kwargs)
 |      Create and return a new object.  See help(type) for accurate signature.
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |
 |  argtypes
 |      specify the argument types
 |
 |  errcheck
 |      a function to check for errors
 |
 |  restype
 |      specify the result type
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from _CData:
 |
 |  __ctypes_from_outparam__(...)
 |
 |  __hash__(self, /)
 |      Return hash(self).
 |
 |  __reduce__(...)
 |      Helper for pickle.
 |
 |  __setstate__(...)

Could it be a typo in the documentation?

Linked PRs

eryksun commented 3 months ago

It's a mistake in the docs, but the source of the mistake is understandable. Instances of ctypes.CDLL create a dynamic _FuncPtr subclass of ctypes._CFuncPtr, with a particular _restype_ and _flags_. For example:

>>> lib = ctypes.CDLL(None)
>>> issubclass(lib._FuncPtr, ctypes._CFuncPtr)
True 
>>> hasattr(ctypes._CFuncPtr, '_restype_')
False
>>> hasattr(ctypes._CFuncPtr, '_flags_')
False
>>> lib._FuncPtr._restype_
<class 'ctypes.c_int'>
>>> lib._FuncPtr._flags_ == ctypes._FUNCFLAG_CDECL
True

>>> lib2 = ctypes.CDLL(None, use_errno=True)
>>> lib2._FuncPtr._flags_ == ctypes._FUNCFLAG_CDECL | ctypes._FUNCFLAG_USE_ERRNO
True
vmonteco commented 3 months ago

It's a mistake in the docs, but the source of the mistake is understandable. Instances of ctypes.CDLL create a dynamic _FuncPtr subclass of ctypes._CFuncPtr, with a particular _restype_ and _flags_. For example:

>>> lib = ctypes.CDLL(None)
>>> issubclass(lib._FuncPtr, ctypes._CFuncPtr)
True 
>>> hasattr(ctypes._CFuncPtr, '_restype_')
False
>>> hasattr(ctypes._CFuncPtr, '_flags_')
False
>>> lib._FuncPtr._restype_
<class 'ctypes.c_int'>
>>> lib._FuncPtr._flags_ == ctypes._FUNCFLAG_CDECL
True

>>> lib2 = ctypes.CDLL(None, use_errno=True)
>>> lib2._FuncPtr._flags_ == ctypes._FUNCFLAG_CDECL | ctypes._FUNCFLAG_USE_ERRNO
True

I see, thank you for the explanation.