You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
ctypes automatic byref failing on custom classes attributes #71990
When using a custom class to store a ctype value, passing that class as a function argument explicitly declared to be a pointer type fails to pass the _as_parameter_ class attribute as a pointer and instead raises a TypeError.
For example:
>>> from ctypes import*
>>> from ctypes.wintypes import*
>>>
>>> classCustomPHKEY(object):
... def__init__(self, value):
... self._as_parameter_ = HKEY(value)
...
>>>
>>> function = windll.function
>>> function.argtypes = [POINTER(HKEY)]
>>> function.restype =LONG
>>> result = CustomPHKEY(0)
>>> function(result)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ctypes.ArgumentError: argument 1: <type 'exceptions.TypeError'>: expected LP_c_void_p instance instead of c_void_p
Shouldn't ctypes apply the required byref() conversion automatically? Or is this behavior normal and automatic byref() only concerns native ctypes types?
I only flagged Python 3.5 and Python 2.7 since they are the only ones I explicitly tested this on but I suspect other versions are affected.
Traceback (most recent call last):
File "F:\Python\mypy\tem.py", line 8, in <module>
function = windll.function
File "C:\Programs\Python36\lib\ctypes\__init__.py", line 417, in __getattr__
dll =self._dlltype(name)
File "C:\Programs\Python36\lib\ctypes\__init__.py", line 347, in __init__self._handle = _dlopen(self._name, mode)
OSError: [WinError 126] The specified module could not be found
Terry, the provided example is incomplete and doesn't make sense as it stands. For better or worse, windll.dllname attempts to load WinDLL(dllname) and cache the resulting library on the windll loader. (The library in turn caches function pointers, which means this design is a problem waiting to happen, which has happened a few times with various projects conflicting with each other over windll.kernel32 function prototypes. I recommend using WinDLL instead.)
I gather that Erwan wants ctypes.byref() and the implicit _byref that's called by PyCPointerType_from_param to be enhanced to support objects that define _as_parameter_. So I'm changing the issue type accordingly.
I can confirm Eryk got what I meant. I didn't know if it was meant to work that way or if it was simply something that was overlooked so I thought I'd ask, I will look into the ctypes code to provide a patch sometime this week if I can.
Terry, for a working example take the following (on a MS Windows):
>>> from ctypes import*
>>> from ctypes.wintypes import*
>>>
>>> classCustomPHKEY(object):
... def__init__(self, value):
... self._as_parameter_ = HKEY(value)
...
>>>
>>> function = ctypes.windll.advapi32.RegOpenKeyExW
>>> function.argtypes = [HKEY, c_wchar_p, DWORD, DWORD, POINTER(HKEY)]
>>> function.restype =LONG
>>> result = CustomPHKEY(0)
>>> function(0x80000002, 'SOFTWARE', 0, 0x20019, result)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ctypes.ArgumentError: argument 5: <type 'exceptions.TypeError'>: expected LP_c_void_p instance instead of c_void_p
Activity
lepaperwan commentedon Aug 19, 2016
When using a custom class to store a ctype value, passing that class as a function argument explicitly declared to be a pointer type fails to pass the _as_parameter_ class attribute as a pointer and instead raises a TypeError.
Shouldn't ctypes apply the required byref() conversion automatically? Or is this behavior normal and automatic byref() only concerns native ctypes types?
I only flagged Python 3.5 and Python 2.7 since they are the only ones I explicitly tested this on but I suspect other versions are affected.
terryjreedy commentedon Aug 26, 2016
I ran the the following, which I don't understand, and therefore don't what should happen, on Win 10, 3.6.0a3.
eryksun commentedon Aug 27, 2016
Terry, the provided example is incomplete and doesn't make sense as it stands. For better or worse, windll.dllname attempts to load WinDLL(dllname) and cache the resulting library on the windll loader. (The library in turn caches function pointers, which means this design is a problem waiting to happen, which has happened a few times with various projects conflicting with each other over windll.kernel32 function prototypes. I recommend using WinDLL instead.)
I gather that Erwan wants ctypes.byref() and the implicit _byref that's called by PyCPointerType_from_param to be enhanced to support objects that define _as_parameter_. So I'm changing the issue type accordingly.
lepaperwan commentedon Aug 29, 2016
I can confirm Eryk got what I meant. I didn't know if it was meant to work that way or if it was simply something that was overlooked so I thought I'd ask, I will look into the ctypes code to provide a patch sometime this week if I can.