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

Reply via email to