Eryk Sun added the comment:
> I would strongly argue to generally prohibit this
> with an exception
I agree. A warning in the tutorial isn't sufficient. ctypes should raise an
error when setting a union or bitfield struct type in argtypes or when passing
one by value.
Here's some background to flesh out this issue. Both struct and union types are
defined as the libffi type FFI_TYPE_STRUCT (13), since FFI_TYPE_UNION doesn't
exist.
class MyUnion(ctypes.Union):
_fields_ = [("x%s" % i, ctypes.c_double) for i in range(11)]
>>> stgdict(MyUnion).length
11
>>> stgdict(MyUnion).ffi_type_pointer
size: 8
alignment: 8
type: 13
elements: 17918992
>>> (ctypes.c_void_p * 12).from_address(17918992)[:]
[140354450953784, 140354450953784, 140354450953784, 140354450953784,
140354450953784, 140354450953784, 140354450953784, 140354450953784,
140354450953784, 140354450953784, 140354450953784, None]
>>> ffi_type.from_address(140354450953784)
size: 8
alignment: 8
type: 3
elements: LP_LP_ffi_type(<NULL>)
Type 3 is FFI_TYPE_DOUBLE.
class MyStruct(ctypes.Structure):
_fields_ = [("x%s" % i, ctypes.c_double) for i in range(11)]
>>> stgdict(MyStruct).length
11
>>> stgdict(MyStruct).ffi_type_pointer
size: 88
alignment: 8
type: 13
elements: 17868096
>>> (ctypes.c_void_p * 12).from_address(17868096)[:]
[140354450953784, 140354450953784, 140354450953784, 140354450953784,
140354450953784, 140354450953784, 140354450953784, 140354450953784,
140354450953784, 140354450953784, 140354450953784, None]
As shown above, FFI_TYPE_STRUCT uses the `elements` array in its ffi_type. Each
element is a pointer to an ffi_type for the corresponding field in the struct
or union. This array is terminated by a NULL pointer.
The C data size of a MyUnion instance is 8 bytes. This is less than 32 bytes
(i.e. four 8-byte words), so the code in classify_argument rightfully assumes
the argument won't be passed on the stack. Thus it classifies the register
type(s) to use, presuming it's dealing with a struct. But since it's a union
the total size of the elements is unrelated to the union's size. libffi would
need to implement an FFI_TYPE_UNION type to support this as a separate case.
Otherwise ctypes needs to actively forbid passing a union by value.
----------
nosy: +eryksun
versions: +Python 3.6
_______________________________________
Python tracker <[email protected]>
<http://bugs.python.org/issue26628>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com