If a callback function returns a ctypes._SimpleCData object, it will fail with a type error and complain that it expects a basic type.
Using the qsort example:
def py_cmp_func(a, b):
print(a.contents, b.contents)
return c_int(0)
> TypeError: an integer is required (got type c_int)
> Exception ignored in: <function py_cmp_func at 0x2439648>
This is somewhat surprising as it is totally fine to pass a c_int (or an int) as an c_int argument. But this is really an issue for subclasses of fundamental data types:
(sticking with qsort for simplicity, full example attached)
class CmpRet(c_int):
pass
cmp_ctype = CFUNCTYPE(CmpRet, POINTER(c_int), POINTER(c_int))
def py_cmp_func(a, b):
print(a.contents, b.contents)
return CmpRet(0)
> TypeError: an integer is required (got type CmpRet)
> Exception ignored in: <function py_cmp_func at 0x1049cf8>
This is inconsistent with the no transparent argument/return type conversion rule for subclasses.
Consider for instance an enum with a specific underlying type. A subclass (with __eq__ on value) from the corresponding ctype can be useful to provide a typesafe way to pass / receive those from C. Due to the described behavior, this doesn't work for callbacks.
This is related to #5710, that discusses composite types.
|