Eryk Sun added the comment: classify_argument is in Modules/_ctypes/libffi/src/x86/ffi64.c. This file is for the 64-bit Unix ABI. libffi doesn't use it for 64-bit Windows.
Some (all?) Linux distros link ctypes to the system libffi. In my experience, building 3.6 on Linux defaults to the system libffi, and I don't personally know how to override this. Configuring "--without-system-ffi" seems to be ignored. Regarding your Test struct example, it's ok in this particular case to classify an 8-byte integer array the same as an 8-byte pointer. It doesn't abort() because the 2nd word isn't left unclassified (i.e. X86_64_NO_CLASS). import ctypes class Test(ctypes.Structure): _fields_ = (('foo', ctypes.c_int), ('bar', ctypes.c_int), ('data', ctypes.c_uint8 * 8)) @ctypes.CFUNCTYPE(None, Test) def func(t): print('foo:', t.foo) print('bar:', t.bar) print('data:', t.data[:]) t = Test(5, 10, tuple(range(8))) >>> hex(id(Test)) '0x9d8ad8' The ctypes Structure has 3 elements. The first two are ffi_type_sint32 (FFI_TYPE_SINT32 == 10), and the third is ffi_type_pointer (FFI_TYPE_POINTER == 14): (gdb) set $dict = (StgDictObject *)(((PyTypeObject *)0x9d8ad8)->tp_dict) (gdb) p *$dict->ffi_type_pointer->elements[0] $1 = {size = 4, alignment = 4, type = 10, elements = 0x0} (gdb) p *$dict->ffi_type_pointer->elements[1] $2 = {size = 4, alignment = 4, type = 10, elements = 0x0} (gdb) p *$dict->ffi_type_pointer->elements[2] $3 = {size = 8, alignment = 8, type = 14, elements = 0x0} (gdb) p $dict->ffi_type_pointer->elements[3] $4 = (struct _ffi_type *) 0x0 classify_argument() recursively classifies and merges these elements. The first two get merged as X86_64_INTEGER_CLASS, and the 'pointer' (actually an array) is X86_64_INTEGER_CLASS. >>> func(t) Breakpoint 1, ffi_call (cif=cif@entry=0x7fffffffd570, fn=fn@entry=0x7ffff7fee010, rvalue=rvalue@entry=0x7fffffffd630, avalue=avalue@entry=0x7fffffffd610) at ../src/x86/ffi64.c:424 [...snip...] 458 for (i = 0; i < avn; ++i) (gdb) 462 n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse); (gdb) 463 if (n == 0 (gdb) p n $6 = 2 (gdb) p ngpr $7 = 2 (gdb) p classes[0] $8 = X86_64_INTEGER_CLASS (gdb) p classes[1] $9 = X86_64_INTEGER_CLASS The struct is passed in two general-purpose integer registers, rdi and rsi: Breakpoint 2, ffi_call_unix64 () at ../src/x86/unix64.S:49 49 movq (%rsp), %r10 /* Load return address. */ [...snip...] 76 call *%r11 (gdb) p/x $rdi $10 = 0xa00000005 (gdb) p/x $rsi $11 = 0x706050403020100 (gdb) c Continuing. foo: 5 bar: 10 data: [0, 1, 2, 3, 4, 5, 6, 7] ---------- _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue22273> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com