Issue #20160: Merged fix from 3.4.
This commit is contained in:
commit
0b588869ee
|
@ -1,3 +1,4 @@
|
||||||
|
import functools
|
||||||
import unittest
|
import unittest
|
||||||
from ctypes import *
|
from ctypes import *
|
||||||
from ctypes.test import need_symbol
|
from ctypes.test import need_symbol
|
||||||
|
@ -240,6 +241,40 @@ class SampleCallbacksTestCase(unittest.TestCase):
|
||||||
self.assertEqual(result,
|
self.assertEqual(result,
|
||||||
callback(1.1*1.1, 2.2*2.2, 3.3*3.3, 4.4*4.4, 5.5*5.5))
|
callback(1.1*1.1, 2.2*2.2, 3.3*3.3, 4.4*4.4, 5.5*5.5))
|
||||||
|
|
||||||
|
def test_callback_large_struct(self):
|
||||||
|
class Check: pass
|
||||||
|
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [
|
||||||
|
('first', c_ulong),
|
||||||
|
('second', c_ulong),
|
||||||
|
('third', c_ulong),
|
||||||
|
]
|
||||||
|
|
||||||
|
def callback(check, s):
|
||||||
|
check.first = s.first
|
||||||
|
check.second = s.second
|
||||||
|
check.third = s.third
|
||||||
|
|
||||||
|
check = Check()
|
||||||
|
s = X()
|
||||||
|
s.first = 0xdeadbeef
|
||||||
|
s.second = 0xcafebabe
|
||||||
|
s.third = 0x0bad1dea
|
||||||
|
|
||||||
|
CALLBACK = CFUNCTYPE(None, X)
|
||||||
|
dll = CDLL(_ctypes_test.__file__)
|
||||||
|
func = dll._testfunc_cbk_large_struct
|
||||||
|
func.argtypes = (X, CALLBACK)
|
||||||
|
func.restype = None
|
||||||
|
# the function just calls the callback with the passed structure
|
||||||
|
func(s, CALLBACK(functools.partial(callback, check)))
|
||||||
|
self.assertEqual(check.first, s.first)
|
||||||
|
self.assertEqual(check.second, s.second)
|
||||||
|
self.assertEqual(check.third, s.third)
|
||||||
|
self.assertEqual(check.first, 0xdeadbeef)
|
||||||
|
self.assertEqual(check.second, 0xcafebabe)
|
||||||
|
self.assertEqual(check.third, 0x0bad1dea)
|
||||||
|
|
||||||
################################################################
|
################################################################
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,24 @@ _testfunc_cbk_reg_double(double a, double b, double c, double d, double e,
|
||||||
return func(a*a, b*b, c*c, d*d, e*e);
|
return func(a*a, b*b, c*c, d*d, e*e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This structure should be the same as in test_callbacks.py and the
|
||||||
|
* method test_callback_large_struct. See issues 17310 and 20160: the
|
||||||
|
* structure must be larger than 8 bytes long.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned long first;
|
||||||
|
unsigned long second;
|
||||||
|
unsigned long third;
|
||||||
|
} Test;
|
||||||
|
|
||||||
|
EXPORT(void)
|
||||||
|
_testfunc_cbk_large_struct(Test in, void (*func)(Test))
|
||||||
|
{
|
||||||
|
func(in);
|
||||||
|
}
|
||||||
|
|
||||||
EXPORT(void)testfunc_array(int values[4])
|
EXPORT(void)testfunc_array(int values[4])
|
||||||
{
|
{
|
||||||
printf("testfunc_array %d %d %d %d\n",
|
printf("testfunc_array %d %d %d %d\n",
|
||||||
|
|
|
@ -378,7 +378,7 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
|
||||||
|
|
||||||
if ( cif->rtype->type == FFI_TYPE_STRUCT ) {
|
if ( cif->rtype->type == FFI_TYPE_STRUCT ) {
|
||||||
*rvalue = *(void **) argp;
|
*rvalue = *(void **) argp;
|
||||||
argp += 4;
|
argp += sizeof(void *);
|
||||||
}
|
}
|
||||||
|
|
||||||
p_argv = avalue;
|
p_argv = avalue;
|
||||||
|
@ -389,13 +389,23 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
|
||||||
|
|
||||||
/* Align if necessary */
|
/* Align if necessary */
|
||||||
if ((sizeof(char *) - 1) & (size_t) argp) {
|
if ((sizeof(char *) - 1) & (size_t) argp) {
|
||||||
argp = (char *) ALIGN(argp, sizeof(char*));
|
argp = (char *) ALIGN(argp, sizeof(char*));
|
||||||
}
|
}
|
||||||
|
|
||||||
z = (*p_arg)->size;
|
z = (*p_arg)->size;
|
||||||
|
|
||||||
/* because we're little endian, this is what it turns into. */
|
/* because we're little endian, this is what it turns into. */
|
||||||
|
|
||||||
|
#ifdef _WIN64
|
||||||
|
if (z > 8) {
|
||||||
|
/* On Win64, if a single argument takes more than 8 bytes,
|
||||||
|
* then it is always passed by reference.
|
||||||
|
*/
|
||||||
|
*p_argv = *((void**) argp);
|
||||||
|
z = 8;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
*p_argv = (void*) argp;
|
*p_argv = (void*) argp;
|
||||||
|
|
||||||
p_argv++;
|
p_argv++;
|
||||||
|
|
Loading…
Reference in New Issue