summaryrefslogtreecommitdiff
path: root/Modules/_ctypes
diff options
context:
space:
mode:
authorErik Bray <erik.m.bray@gmail.com>2017-06-07 18:42:24 +0100
committerVinay Sajip <vinay_sajip@yahoo.co.uk>2017-06-07 18:42:24 +0100
commit9ba3aa4d02a110d1a1ea464a8aff3be7dd9c63c3 (patch)
treeb9ffda17e8b2462c8a859531b645c79a473055f2 /Modules/_ctypes
parent897bba75632dfce87c355e3cd4700468357715a7 (diff)
downloadcpython-git-9ba3aa4d02a110d1a1ea464a8aff3be7dd9c63c3.tar.gz
bpo-30353: Fix pass by value for structs on 64-bit Cygwin/MinGW (GH-1559)
Diffstat (limited to 'Modules/_ctypes')
-rw-r--r--Modules/_ctypes/_ctypes_test.c18
-rw-r--r--Modules/_ctypes/callproc.c23
2 files changed, 39 insertions, 2 deletions
diff --git a/Modules/_ctypes/_ctypes_test.c b/Modules/_ctypes/_ctypes_test.c
index fe0015c801..2255e57339 100644
--- a/Modules/_ctypes/_ctypes_test.c
+++ b/Modules/_ctypes/_ctypes_test.c
@@ -57,6 +57,24 @@ _testfunc_large_struct_update_value(Test in)
((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])
{
printf("testfunc_array %d %d %d %d\n",
diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c
index 0b6faf96c6..5439b939dc 100644
--- a/Modules/_ctypes/callproc.c
+++ b/Modules/_ctypes/callproc.c
@@ -1039,6 +1039,13 @@ GetComError(HRESULT errcode, GUID *riid, IUnknown *pIunk)
}
#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:
* - argtuple is tuple of arguments
@@ -1136,8 +1143,20 @@ PyObject *_ctypes_callproc(PPROC pProc,
}
for (i = 0; i < argcount; ++i) {
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;
else
avalues[i] = (void *)&args[i].value;