[3.6] bpo-30353: Fix pass by value for structs on 64-bit Cygwin/MinGW (GH-1559) (GH-5954)
(cherry picked from commit 9ba3aa4d02
)
Co-authored-by: Erik Bray <erik.m.bray@gmail.com>
This commit is contained in:
parent
15425cf245
commit
2f3ba27185
|
@ -169,6 +169,10 @@ class BasicWrapTestCase(unittest.TestCase):
|
||||||
s2h = dll.ret_2h_func(self.wrap(inp))
|
s2h = dll.ret_2h_func(self.wrap(inp))
|
||||||
self.assertEqual((s2h.x, s2h.y), (99*2, 88*3))
|
self.assertEqual((s2h.x, s2h.y), (99*2, 88*3))
|
||||||
|
|
||||||
|
# Test also that the original struct was unmodified (i.e. was passed by
|
||||||
|
# value)
|
||||||
|
self.assertEqual((inp.x, inp.y), (99, 88))
|
||||||
|
|
||||||
def test_struct_return_8H(self):
|
def test_struct_return_8H(self):
|
||||||
class S8I(Structure):
|
class S8I(Structure):
|
||||||
_fields_ = [("a", c_int),
|
_fields_ = [("a", c_int),
|
||||||
|
|
|
@ -417,6 +417,28 @@ class StructureTestCase(unittest.TestCase):
|
||||||
self.assertEqual(s.second, 0xcafebabe)
|
self.assertEqual(s.second, 0xcafebabe)
|
||||||
self.assertEqual(s.third, 0x0bad1dea)
|
self.assertEqual(s.third, 0x0bad1dea)
|
||||||
|
|
||||||
|
def test_pass_by_value_in_register(self):
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [
|
||||||
|
('first', c_uint),
|
||||||
|
('second', c_uint)
|
||||||
|
]
|
||||||
|
|
||||||
|
s = X()
|
||||||
|
s.first = 0xdeadbeef
|
||||||
|
s.second = 0xcafebabe
|
||||||
|
dll = CDLL(_ctypes_test.__file__)
|
||||||
|
func = dll._testfunc_reg_struct_update_value
|
||||||
|
func.argtypes = (X,)
|
||||||
|
func.restype = None
|
||||||
|
func(s)
|
||||||
|
self.assertEqual(s.first, 0xdeadbeef)
|
||||||
|
self.assertEqual(s.second, 0xcafebabe)
|
||||||
|
got = X.in_dll(dll, "last_tfrsuv_arg")
|
||||||
|
self.assertEqual(s.first, got.first)
|
||||||
|
self.assertEqual(s.second, got.second)
|
||||||
|
|
||||||
|
|
||||||
class PointerMemberTestCase(unittest.TestCase):
|
class PointerMemberTestCase(unittest.TestCase):
|
||||||
|
|
||||||
def test(self):
|
def test(self):
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Fix ctypes pass-by-value for structs on 64-bit Cygwin/MinGW.
|
|
@ -57,6 +57,24 @@ _testfunc_large_struct_update_value(Test in)
|
||||||
((volatile Test *)&in)->third = 0x0badf00d;
|
((volatile Test *)&in)->third = 0x0badf00d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned int first;
|
||||||
|
unsigned int second;
|
||||||
|
} TestReg;
|
||||||
|
|
||||||
|
|
||||||
|
EXPORT(TestReg) last_tfrsuv_arg;
|
||||||
|
|
||||||
|
|
||||||
|
EXPORT(void)
|
||||||
|
_testfunc_reg_struct_update_value(TestReg in)
|
||||||
|
{
|
||||||
|
last_tfrsuv_arg = in;
|
||||||
|
((volatile TestReg *)&in)->first = 0x0badf00d;
|
||||||
|
((volatile TestReg *)&in)->second = 0x0badf00d;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
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",
|
||||||
|
|
|
@ -1040,6 +1040,13 @@ GetComError(HRESULT errcode, GUID *riid, IUnknown *pIunk)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (defined(__x86_64__) && (defined(__MINGW64__) || defined(__CYGWIN__))) || \
|
||||||
|
defined(__aarch64__)
|
||||||
|
#define CTYPES_PASS_BY_REF_HACK
|
||||||
|
#define POW2(x) (((x & ~(x - 1)) == x) ? x : 0)
|
||||||
|
#define IS_PASS_BY_REF(x) (x > 8 || !POW2(x))
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Requirements, must be ensured by the caller:
|
* Requirements, must be ensured by the caller:
|
||||||
* - argtuple is tuple of arguments
|
* - argtuple is tuple of arguments
|
||||||
|
@ -1137,8 +1144,20 @@ PyObject *_ctypes_callproc(PPROC pProc,
|
||||||
}
|
}
|
||||||
for (i = 0; i < argcount; ++i) {
|
for (i = 0; i < argcount; ++i) {
|
||||||
atypes[i] = args[i].ffi_type;
|
atypes[i] = args[i].ffi_type;
|
||||||
if (atypes[i]->type == FFI_TYPE_STRUCT
|
#ifdef CTYPES_PASS_BY_REF_HACK
|
||||||
)
|
size_t size = atypes[i]->size;
|
||||||
|
if (IS_PASS_BY_REF(size)) {
|
||||||
|
void *tmp = alloca(size);
|
||||||
|
if (atypes[i]->type == FFI_TYPE_STRUCT)
|
||||||
|
memcpy(tmp, args[i].value.p, size);
|
||||||
|
else
|
||||||
|
memcpy(tmp, (void*)&args[i].value, size);
|
||||||
|
|
||||||
|
avalues[i] = tmp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
if (atypes[i]->type == FFI_TYPE_STRUCT)
|
||||||
avalues[i] = (void *)args[i].value.p;
|
avalues[i] = (void *)args[i].value.p;
|
||||||
else
|
else
|
||||||
avalues[i] = (void *)&args[i].value;
|
avalues[i] = (void *)&args[i].value;
|
||||||
|
|
Loading…
Reference in New Issue