Author: Armin Rigo <[email protected]>
Branch: win32-stdcall
Changeset: r2303:826248f909c5
Date: 2015-10-05 19:25 +0200
http://bitbucket.org/cffi/cffi/changeset/826248f909c5/
Log: A branch to implement "__stdcall" more completely on Windows.
Initial tests
diff --git a/testing/cffi0/test_function.py b/testing/cffi0/test_function.py
--- a/testing/cffi0/test_function.py
+++ b/testing/cffi0/test_function.py
@@ -427,3 +427,48 @@
res = m.QueryPerformanceFrequency(p_freq)
assert res != 0
assert p_freq[0] != 0
+
+ def test_explicit_cdecl_stdcall(self):
+ if sys.platform != 'win32':
+ py.test.skip("Windows-only test")
+ if self.Backend is CTypesBackend:
+ py.test.skip("not with the ctypes backend")
+ #
+ ffi = FFI(backend=self.Backend())
+ ffi.cdef("""
+ BOOL QueryPerformanceFrequency(LONGLONG *lpFrequency);
+ """)
+ m = ffi.dlopen("Kernel32.dll")
+ tp = ffi.typeof(m.QueryPerformanceFrequency)
+ assert 'stdcall' not in str(tp) and 'cdecl' not in str(tp)
+ assert tp is (
+ ffi.typeof(ffi.addressof(m, 'QueryPerformanceFrequency')).item)
+ #
+ ffi = FFI(backend=self.Backend())
+ ffi.cdef("""
+ BOOL QueryPerformanceFrequency(LONGLONG *lpFrequency);
+ """, calling_conv="cdecl")
+ m = ffi.dlopen("Kernel32.dll")
+ tpc = ffi.typeof(m.QueryPerformanceFrequency)
+ assert tpc is tp
+ assert tpc is (
+ ffi.typeof(ffi.addressof(m, 'QueryPerformanceFrequency')).item)
+ #
+ ffi = FFI(backend=self.Backend())
+ ffi.cdef("""
+ BOOL QueryPerformanceFrequency(LONGLONG *lpFrequency);
+ """, calling_conv="stdcall")
+ m = ffi.dlopen("Kernel32.dll")
+ tps = ffi.typeof(m.QueryPerformanceFrequency)
+ assert tps is not tpc
+ assert '__stdcall' in str(tps) and 'cdecl' not in str(tps)
+ assert tps is (
+ ffi.typeof(ffi.addressof(m, 'QueryPerformanceFrequency')).item)
+ #
+ ffi = FFI(backend=self.Backend())
+ ffi.cdef("typedef int (*fnc_t)(int);", calling_conv="cdecl")
+ ffi.cdef("typedef int (*fns_t)(int);", calling_conv="stdcall")
+ tpc = ffi.typeof("fnc_t")
+ tps = ffi.typeof("fns_t")
+ assert str(tpc) == "<ctype 'int(*)(int)'>"
+ assert str(tps) == "<ctype 'int(__stdcall *)(int)'>"
diff --git a/testing/cffi0/test_verify.py b/testing/cffi0/test_verify.py
--- a/testing/cffi0/test_verify.py
+++ b/testing/cffi0/test_verify.py
@@ -1221,7 +1221,6 @@
assert lib.sin(1.23) == math.sin(1.23)
def test_callback_calling_convention():
- py.test.skip("later")
if sys.platform != 'win32':
py.test.skip("Windows only")
ffi = FFI()
diff --git a/testing/cffi1/test_recompiler.py b/testing/cffi1/test_recompiler.py
--- a/testing/cffi1/test_recompiler.py
+++ b/testing/cffi1/test_recompiler.py
@@ -1280,3 +1280,57 @@
""")
assert lib.aaa == 42
py.test.raises(AttributeError, "lib.aaa = 43")
+
+def test_win32_calling_convention_1():
+ if sys.platform != 'win32':
+ py.test.skip("Windows only")
+ ffi = FFI()
+ ffi.cdef("int call1(int(*cb)(int)); int cb1(int);", calling_conv="cdecl")
+ ffi.cdef("int call2(int(*cb)(int)); int cb2(int);", calling_conv="stdcall")
+ lib = verify(ffi, 'test_win32_calling_convention_1', """
+ int __cdecl call1(int(*__cdecl cb)(int)) {
+ int i, result = 0;
+ for (i = 0; i < 1000; i++)
+ result += cb(i);
+ return result;
+ }
+ int __stdcall call2(int(*__stdcall cb)(int)) {
+ int i, result = 0;
+ for (i = 0; i < 1000; i++)
+ result += cb(-i);
+ return result;
+ }
+ int __cdecl cb1(int x) { return x * 2; }
+ int __stdcall cb2(int x) { return x * 3; }
+ """)
+ assert lib.call1(ffi.addressof(lib, 'cb1')) == 500*999*2
+ assert lib.call2(ffi.addressof(lib, 'cb2')) == -500*999*3
+
+def test_win32_calling_convention_2():
+ if sys.platform != 'win32':
+ py.test.skip("Windows only")
+ # any mistake in the declaration of plain function (including the
+ # precise argument types and, here, the calling convention) are
+ # automatically corrected. But this does not apply to the 'cb'
+ # function pointer argument.
+ ffi = FFI()
+ ffi.cdef("int call1(int(*cb)(int)); int cb1(int);", calling_conv="cdecl")
+ ffi.cdef("int call2(int(*cb)(int)); int cb2(int);", calling_conv="stdcall")
+ lib = verify(ffi, 'test_win32_calling_convention_2', """
+ int __stdcall call1(int(*__cdecl cb)(int)) {
+ int i, result = 0;
+ for (i = 0; i < 1000; i++)
+ result += cb(i);
+ return result;
+ }
+ int __cdecl call2(int(*__stdcall cb)(int)) {
+ int i, result = 0;
+ for (i = 0; i < 1000; i++)
+ result += cb(-i);
+ return result;
+ }
+ int __stdcall cb1(int x) { return x * 2; }
+ int __cdecl cb2(int x) { return x * 3; }
+ """)
+ assert lib.call1(ffi.addressof(lib, 'cb1')) == 500*999*2
+ assert lib.call2(ffi.addressof(lib, 'cb2')) == -500*999*3
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit