Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b00697e

Browse files
author
Thomas Heller
committed
Merged revisions 82126-82127 via svnmerge from
svn+ssh://[email protected]/python/trunk ........ r82126 | thomas.heller | 2010-06-21 16:00:24 +0200 (Mo, 21 Jun 2010) | 1 line Fix #8959 by reverting revision 80761. ........ r82127 | thomas.heller | 2010-06-21 17:01:18 +0200 (Mo, 21 Jun 2010) | 2 lines Add tests for problems reported in issue 8959. ........
1 parent 31b16a5 commit b00697e

16 files changed

Lines changed: 1986 additions & 376 deletions

File tree

Lib/ctypes/test/test_callbacks.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,41 @@ def func(x):
166166

167167
self.assertTrue(diff < 0.01, "%s not less than 0.01" % diff)
168168

169+
def test_issue_8959_a(self):
170+
from ctypes.util import find_library
171+
libc_path = find_library("c")
172+
if not libc_path:
173+
return # cannot test
174+
libc = CDLL(libc_path)
175+
176+
@CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))
177+
def cmp_func(a, b):
178+
return a[0] - b[0]
179+
180+
array = (c_int * 5)(5, 1, 99, 7, 33)
181+
182+
libc.qsort(array, len(array), sizeof(c_int), cmp_func)
183+
self.assertEqual(array[:], [1, 5, 7, 33, 99])
184+
185+
try:
186+
WINFUNCTYPE
187+
except NameError:
188+
pass
189+
else:
190+
def test_issue_8959_b(self):
191+
from ctypes.wintypes import BOOL, HWND, LPARAM
192+
global windowCount
193+
windowCount = 0
194+
195+
@WINFUNCTYPE(BOOL, HWND, LPARAM)
196+
def EnumWindowsCallbackFunc(hwnd, lParam):
197+
global windowCount
198+
windowCount += 1
199+
return True #Allow windows to keep enumerating
200+
201+
windll.user32.EnumWindows(EnumWindowsCallbackFunc, 0)
202+
self.assertFalse(windowCount == 0)
203+
169204
################################################################
170205

171206
if __name__ == '__main__':

Lib/ctypes/test/test_win32.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,32 @@
66

77
import _ctypes_test
88

9+
if sys.platform == "win32" and sizeof(c_void_p) == sizeof(c_int):
10+
# Only windows 32-bit has different calling conventions.
11+
12+
class WindowsTestCase(unittest.TestCase):
13+
def test_callconv_1(self):
14+
# Testing stdcall function
15+
16+
IsWindow = windll.user32.IsWindow
17+
# ValueError: Procedure probably called with not enough arguments (4 bytes missing)
18+
self.assertRaises(ValueError, IsWindow)
19+
20+
# This one should succeeed...
21+
self.assertEqual(0, IsWindow(0))
22+
23+
# ValueError: Procedure probably called with too many arguments (8 bytes in excess)
24+
self.assertRaises(ValueError, IsWindow, 0, 0, 0)
25+
26+
def test_callconv_2(self):
27+
# Calling stdcall function as cdecl
28+
29+
IsWindow = cdll.user32.IsWindow
30+
31+
# ValueError: Procedure called with not enough arguments (4 bytes missing)
32+
# or wrong calling convention
33+
self.assertRaises(ValueError, IsWindow, None)
34+
935
if sys.platform == "win32":
1036
class FunctionCallTestCase(unittest.TestCase):
1137

Modules/_ctypes/callproc.c

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,7 @@ static int _call_function_pointer(int flags,
761761
ffi_cif cif;
762762
int cc;
763763
#ifdef MS_WIN32
764+
int delta;
764765
#ifndef DONT_USE_SEH
765766
DWORD dwExceptionCode = 0;
766767
EXCEPTION_RECORD record;
@@ -811,8 +812,9 @@ static int _call_function_pointer(int flags,
811812
#ifndef DONT_USE_SEH
812813
__try {
813814
#endif
815+
delta =
814816
#endif
815-
ffi_call(&cif, (void *)pProc, resmem, avalues);
817+
ffi_call(&cif, (void *)pProc, resmem, avalues);
816818
#ifdef MS_WIN32
817819
#ifndef DONT_USE_SEH
818820
}
@@ -844,6 +846,35 @@ static int _call_function_pointer(int flags,
844846
return -1;
845847
}
846848
#endif
849+
#ifdef MS_WIN64
850+
if (delta != 0) {
851+
PyErr_Format(PyExc_RuntimeError,
852+
"ffi_call failed with code %d",
853+
delta);
854+
return -1;
855+
}
856+
#else
857+
if (delta < 0) {
858+
if (flags & FUNCFLAG_CDECL)
859+
PyErr_Format(PyExc_ValueError,
860+
"Procedure called with not enough "
861+
"arguments (%d bytes missing) "
862+
"or wrong calling convention",
863+
-delta);
864+
else
865+
PyErr_Format(PyExc_ValueError,
866+
"Procedure probably called with not enough "
867+
"arguments (%d bytes missing)",
868+
-delta);
869+
return -1;
870+
} else if (delta > 0) {
871+
PyErr_Format(PyExc_ValueError,
872+
"Procedure probably called with too many "
873+
"arguments (%d bytes in excess)",
874+
delta);
875+
return -1;
876+
}
877+
#endif
847878
#endif
848879
if ((flags & FUNCFLAG_PYTHONAPI) && PyErr_Occurred())
849880
return -1;
@@ -1116,7 +1147,11 @@ PyObject *_ctypes_callproc(PPROC pProc,
11161147
}
11171148
for (i = 0; i < argcount; ++i) {
11181149
atypes[i] = args[i].ffi_type;
1119-
if (atypes[i]->type == FFI_TYPE_STRUCT)
1150+
if (atypes[i]->type == FFI_TYPE_STRUCT
1151+
#ifdef _WIN64
1152+
&& atypes[i]->size <= sizeof(void *)
1153+
#endif
1154+
)
11201155
avalues[i] = (void *)args[i].value.p;
11211156
else
11221157
avalues[i] = (void *)&args[i].value;
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
libffi - Copyright (c) 1996-2003 Red Hat, Inc.
2+
3+
Permission is hereby granted, free of charge, to any person obtaining
4+
a copy of this software and associated documentation files (the
5+
``Software''), to deal in the Software without restriction, including
6+
without limitation the rights to use, copy, modify, merge, publish,
7+
distribute, sublicense, and/or sell copies of the Software, and to
8+
permit persons to whom the Software is furnished to do so, subject to
9+
the following conditions:
10+
11+
The above copyright notice and this permission notice shall be included
12+
in all copies or substantial portions of the Software.
13+
14+
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
15+
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17+
IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20+
OTHER DEALINGS IN THE SOFTWARE.

0 commit comments

Comments
 (0)