Eryk Sun <[email protected]> added the comment:
Your example uses POINTER(c_double), not c_void_p. There's no problem with an
actual pointer object (i.e. subclass of ctypes._Pointer). The problem is with
simple types (i.e. immediate subclasses of ctypes._SimpleCData), including
simple pointer types (i.e. c_void_p, c_char_p, c_wchar_p). Simple types are
automatically converted to equivalent Python types when returned from functions
or accessed in aggregates (i.e. structs and arrays). This is generally
convenient, but at times it's a serious problem.
Note that I said this is the case only for immediate subclasses of
_SimpleCData. We can work around the behavior by using a subclass of the given
simple type. For example:
class my_wchar_p(ctypes.c_wchar_p):
pass
class T(ctypes.Structure):
_fields_ = (('s1', ctypes.c_wchar_p),
('s2', my_wchar_p))
>>> t = T('abc', 'def')
>>> t.s1
'abc'
>>> t.s2
my_wchar_p(140497806976112)
>>> t.s2.value
'def'
If desired, we can retain the automatic conversion for function results by
defining a staticmethod or classmethod named "_check_retval_" on the subclass.
This method takes the result as parameter to be checked, possibly converted,
and returned.
One exception is that [wide-]character arrays always get converted into
bytes/strings when accessed as fields of a struct. This is implemented in
PyCField_FromDesc in Modules/_ctypes/cfield.c. We can't easily work around this
hack because it doesn't check whether the base type is an immediate subclass of
_SimpleCData. Instead we have to use the undocumented `offset` attribute. We
can hide this workaround with a private field and a property. For example:
class T(ctypes.Structure):
_fields_ = (('s1', ctypes.c_wchar * 10),
('_s2', ctypes.c_wchar * 10))
@property
def s2(self):
offset = type(self)._s2.offset
return (ctypes.c_wchar * 10).from_buffer(self, offset)
>>> t = T('abc', 'def')
>>> t._s2
'def'
>>> t.s2
<__main__.c_wchar_Array_10 object at 0x7fc82c3a6510>
>>> t.s2.value
'def'
----------
nosy: +eryksun
_______________________________________
Python tracker <[email protected]>
<https://bugs.python.org/issue35390>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com