Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r75847:2b94f0f584a7 Date: 2015-02-13 10:45 +0100 http://bitbucket.org/pypy/pypy/changeset/2b94f0f584a7/
Log: pypy/tool/import_cffi.py diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py --- a/lib_pypy/cffi/__init__.py +++ b/lib_pypy/cffi/__init__.py @@ -5,7 +5,7 @@ from .ffiplatform import VerificationError, VerificationMissing __version__ = "0.8.6+" -__version_info__ = (0, 8, 6) +__version_info__ = (0, 8, 6, "plus") # The verifier module file names are based on the CRC32 of a string that # contains the following version number. It may be older than __version__ diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py --- a/lib_pypy/cffi/api.py +++ b/lib_pypy/cffi/api.py @@ -56,7 +56,7 @@ import _cffi_backend as backend from . import __version__ assert backend.__version__ == __version__, \ - "version mismatch, %s != %s" % (backend.__version__, __version__) + "version mismatch, %s != %s" % (backend.__version__, __version__) # (If you insist you can also try to pass the option # 'backend=backend_ctypes.CTypesBackend()', but don't # rely on it! It's probably not going to work well.) diff --git a/lib_pypy/cffi/backend_ctypes.py b/lib_pypy/cffi/backend_ctypes.py --- a/lib_pypy/cffi/backend_ctypes.py +++ b/lib_pypy/cffi/backend_ctypes.py @@ -2,11 +2,10 @@ from . import model if sys.version_info < (3,): - integer_types = (int, long) bytechr = chr else: unicode = str - integer_types = int + long = int xrange = range bytechr = lambda num: bytes([num]) @@ -181,7 +180,7 @@ address = 0 elif isinstance(source, CTypesData): address = source._cast_to_integer() - elif isinstance(source, integer_types): + elif isinstance(source, (int, long)): address = source else: raise TypeError("bad type for cast to %r: %r" % @@ -358,7 +357,7 @@ is_signed = (ctype(-1).value == -1) # def _cast_source_to_int(source): - if isinstance(source, (integer_types, float)): + if isinstance(source, (int, long, float)): source = int(source) elif isinstance(source, CTypesData): source = source._cast_to_integer() @@ -399,7 +398,7 @@ if kind == 'bool': @classmethod def _cast_from(cls, source): - if not isinstance(source, (integer_types, float)): + if not isinstance(source, (int, long, float)): source = _cast_source_to_int(source) return cls(bool(source)) def __int__(self): @@ -438,7 +437,7 @@ if kind == 'int' or kind == 'byte' or kind == 'bool': @staticmethod def _to_ctypes(x): - if not isinstance(x, integer_types): + if not isinstance(x, (int, long)): if isinstance(x, CTypesData): x = int(x) else: @@ -465,7 +464,7 @@ if kind == 'float': @staticmethod def _to_ctypes(x): - if not isinstance(x, (integer_types, float, CTypesData)): + if not isinstance(x, (int, long, float, CTypesData)): raise TypeError("float expected, got %s" % type(x).__name__) return ctype(x).value @@ -529,14 +528,14 @@ self._own = True def __add__(self, other): - if isinstance(other, integer_types): + if isinstance(other, (int, long)): return self._new_pointer_at(self._address + other * self._bitem_size) else: return NotImplemented def __sub__(self, other): - if isinstance(other, integer_types): + if isinstance(other, (int, long)): return self._new_pointer_at(self._address - other * self._bitem_size) elif type(self) is type(other): @@ -611,7 +610,7 @@ def __init__(self, init): if length is None: - if isinstance(init, integer_types): + if isinstance(init, (int, long)): len1 = init init = None elif kind == 'char' and isinstance(init, bytes): @@ -686,7 +685,7 @@ return CTypesPtr._arg_to_ctypes(value) def __add__(self, other): - if isinstance(other, integer_types): + if isinstance(other, (int, long)): return CTypesPtr._new_pointer_at( ctypes.addressof(self._blob) + other * ctypes.sizeof(BItem._ctype)) diff --git a/lib_pypy/cffi/verifier.py b/lib_pypy/cffi/verifier.py --- a/lib_pypy/cffi/verifier.py +++ b/lib_pypy/cffi/verifier.py @@ -1,4 +1,4 @@ -import sys, os, binascii, shutil +import sys, os, binascii, shutil, io from . import __version_verifier_modules__ from . import ffiplatform @@ -13,6 +13,16 @@ if type == imp.C_EXTENSION] +if sys.version_info >= (3,): + NativeIO = io.StringIO +else: + class NativeIO(io.BytesIO): + def write(self, s): + if isinstance(s, unicode): + s = s.encode('ascii') + super(NativeIO, self).write(s) + + class Verifier(object): def __init__(self, ffi, preamble, tmpdir=None, modulename=None, @@ -144,19 +154,36 @@ self._vengine.collect_types() self._has_module = True - def _write_source(self, file=None): - must_close = (file is None) - if must_close: - _ensure_dir(self.sourcefilename) - file = open(self.sourcefilename, 'w') + def _write_source_to(self, file): self._vengine._f = file try: self._vengine.write_source_to_f() finally: del self._vengine._f - if must_close: - file.close() - if must_close: + + def _write_source(self, file=None): + if file is not None: + self._write_source_to(file) + else: + # Write our source file to an in memory file. + f = NativeIO() + self._write_source_to(f) + source_data = f.getvalue() + + # Determine if this matches the current file + if os.path.exists(self.sourcefilename): + with open(self.sourcefilename, "r") as fp: + needs_written = not (fp.read() == source_data) + else: + needs_written = True + + # Actually write the file out if it doesn't match + if needs_written: + _ensure_dir(self.sourcefilename) + with open(self.sourcefilename, "w") as fp: + fp.write(source_data) + + # Set this flag self._has_source = True def _compile_module(self): diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_ownlib.py b/pypy/module/test_lib_pypy/cffi_tests/test_ownlib.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_ownlib.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_ownlib.py @@ -8,34 +8,137 @@ SOURCE = """\ #include <errno.h> -int test_getting_errno(void) { +#ifdef _WIN32 +#define EXPORT __declspec(dllexport) +#else +#define EXPORT +#endif + +EXPORT int test_getting_errno(void) { errno = 123; return -1; } -int test_setting_errno(void) { +EXPORT int test_setting_errno(void) { return errno; +}; + +typedef struct { + long x; + long y; +} POINT; + +typedef struct { + long left; + long top; + long right; + long bottom; +} RECT; + + +EXPORT int PointInRect(RECT *prc, POINT pt) +{ + if (pt.x < prc->left) + return 0; + if (pt.x > prc->right) + return 0; + if (pt.y < prc->top) + return 0; + if (pt.y > prc->bottom) + return 0; + return 1; +}; + +EXPORT long left = 10; +EXPORT long top = 20; +EXPORT long right = 30; +EXPORT long bottom = 40; + +EXPORT RECT ReturnRect(int i, RECT ar, RECT* br, POINT cp, RECT dr, + RECT *er, POINT fp, RECT gr) +{ + /*Check input */ + if (ar.left + br->left + dr.left + er->left + gr.left != left * 5) + { + ar.left = 100; + return ar; + } + if (ar.right + br->right + dr.right + er->right + gr.right != right * 5) + { + ar.right = 100; + return ar; + } + if (cp.x != fp.x) + { + ar.left = -100; + } + if (cp.y != fp.y) + { + ar.left = -200; + } + switch(i) + { + case 0: + return ar; + break; + case 1: + return dr; + break; + case 2: + return gr; + break; + + } + return ar; } -int my_array[7] = {0, 1, 2, 3, 4, 5, 6}; +EXPORT int my_array[7] = {0, 1, 2, 3, 4, 5, 6}; """ class TestOwnLib(object): Backend = CTypesBackend def setup_class(cls): - if sys.platform == 'win32': - return + cls.module = None from pypy.module.test_lib_pypy.cffi_tests.udir import udir udir.join('testownlib.c').write(SOURCE) - subprocess.check_call( - 'gcc testownlib.c -shared -fPIC -o testownlib.so', - cwd=str(udir), shell=True) - cls.module = str(udir.join('testownlib.so')) + if sys.platform == 'win32': + import os + # did we already build it? + if os.path.exists(str(udir.join('testownlib.dll'))): + cls.module = str(udir.join('testownlib.dll')) + return + # try (not too hard) to find the version used to compile this python + # no mingw + from distutils.msvc9compiler import get_build_version + version = get_build_version() + toolskey = "VS%0.f0COMNTOOLS" % version + toolsdir = os.environ.get(toolskey, None) + if toolsdir is None: + return + productdir = os.path.join(toolsdir, os.pardir, os.pardir, "VC") + productdir = os.path.abspath(productdir) + vcvarsall = os.path.join(productdir, "vcvarsall.bat") + # 64? + arch = 'x86' + if sys.maxsize > 2**32: + arch = 'amd64' + if os.path.isfile(vcvarsall): + cmd = '"%s" %s' % (vcvarsall, arch) + ' & cl.exe testownlib.c ' \ + ' /LD /Fetestownlib.dll' + subprocess.check_call(cmd, cwd = str(udir), shell=True) + cls.module = str(udir.join('testownlib.dll')) + else: + subprocess.check_call( + 'gcc testownlib.c -shared -fPIC -o testownlib.so', + cwd=str(udir), shell=True) + cls.module = str(udir.join('testownlib.so')) def test_getting_errno(self): + if self.module is None: + py.test.skip("fix the auto-generation of the tiny test lib") if sys.platform == 'win32': - py.test.skip("fix the auto-generation of the tiny test lib") + py.test.skip("fails, errno at multiple addresses") ffi = FFI(backend=self.Backend()) ffi.cdef(""" int test_getting_errno(void); @@ -46,8 +149,10 @@ assert ffi.errno == 123 def test_setting_errno(self): + if self.module is None: + py.test.skip("fix the auto-generation of the tiny test lib") if sys.platform == 'win32': - py.test.skip("fix the auto-generation of the tiny test lib") + py.test.skip("fails, errno at multiple addresses") if self.Backend is CTypesBackend and '__pypy__' in sys.modules: py.test.skip("XXX errno issue with ctypes on pypy?") ffi = FFI(backend=self.Backend()) @@ -61,7 +166,7 @@ assert ffi.errno == 42 def test_my_array_7(self): - if sys.platform == 'win32': + if self.module is None: py.test.skip("fix the auto-generation of the tiny test lib") ffi = FFI(backend=self.Backend()) ffi.cdef(""" @@ -81,7 +186,7 @@ assert ownlib.my_array[i] == i def test_my_array_no_length(self): - if sys.platform == 'win32': + if self.module is None: py.test.skip("fix the auto-generation of the tiny test lib") if self.Backend is CTypesBackend: py.test.skip("not supported by the ctypes backend") @@ -101,7 +206,7 @@ assert ownlib.my_array[i] == i def test_keepalive_lib(self): - if sys.platform == 'win32': + if self.module is None: py.test.skip("fix the auto-generation of the tiny test lib") ffi = FFI(backend=self.Backend()) ffi.cdef(""" @@ -119,7 +224,7 @@ assert res == -1 def test_keepalive_ffi(self): - if sys.platform == 'win32': + if self.module is None: py.test.skip("fix the auto-generation of the tiny test lib") ffi = FFI(backend=self.Backend()) ffi.cdef(""" @@ -135,4 +240,46 @@ assert ownlib_r() is not None # kept alive by ffi res = func() assert res == -1 - assert ffi.errno == 123 + if sys.platform != 'win32': # else, errno at multiple addresses + assert ffi.errno == 123 + + def test_struct_by_value(self): + if self.module is None: + py.test.skip("fix the auto-generation of the tiny test lib") + ffi = FFI(backend=self.Backend()) + ffi.cdef(""" + typedef struct { + long x; + long y; + } POINT; + + typedef struct { + long left; + long top; + long right; + long bottom; + } RECT; + + long left, top, right, bottom; + + RECT ReturnRect(int i, RECT ar, RECT* br, POINT cp, RECT dr, + RECT *er, POINT fp, RECT gr); + """) + ownlib = ffi.dlopen(self.module) + + rect = ffi.new('RECT[1]') + pt = ffi.new('POINT[1]') + pt[0].x = 15 + pt[0].y = 25 + rect[0].left = ownlib.left + rect[0].right = ownlib.right + rect[0].top = ownlib.top + rect[0].bottom = ownlib.bottom + + for i in range(4): + ret = ownlib.ReturnRect(i, rect[0], rect, pt[0], rect[0], + rect, pt[0], rect[0]) + assert ret.left == ownlib.left + assert ret.right == ownlib.right + assert ret.top == ownlib.top + assert ret.bottom == ownlib.bottom diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_verify.py b/pypy/module/test_lib_pypy/cffi_tests/test_verify.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_verify.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_verify.py @@ -1368,7 +1368,7 @@ ffi = FFI() ffi.cdef("int foo(int);") f = open(os.path.join(tmpdir, 'foo.h'), 'w') - print >> f, "int foo(int a) { return a + 42; }" + f.write("int foo(int a) { return a + 42; }\n") f.close() lib = ffi.verify('#include "foo.h"', include_dirs=['.'], @@ -2129,7 +2129,7 @@ n = lib.GetModuleFileName(ffi.NULL, outbuf, 500) assert 0 < n < 500 for i in range(n): - print repr(outbuf[i]) + #print repr(outbuf[i]) assert ord(outbuf[i]) != 0 assert ord(outbuf[n]) == 0 assert ord(outbuf[0]) < 128 # should be a letter, or '\' diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_version.py b/pypy/module/test_lib_pypy/cffi_tests/test_version.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_version.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_version.py @@ -17,6 +17,7 @@ def test_version(): v = cffi.__version__ version_info = '.'.join(str(i) for i in cffi.__version_info__) + version_info = version_info.replace('.plus', '+') assert v == version_info #v = BACKEND_VERSIONS.get(v, v) assert v == _cffi_backend.__version__ @@ -32,7 +33,7 @@ def test_doc_version_file(): parent = os.path.dirname(os.path.dirname(__file__)) - v = cffi.__version__ + v = cffi.__version__.replace('+', '') p = os.path.join(parent, 'doc', 'source', 'index.rst') content = open(p).read() assert ("cffi/cffi-%s.tar.gz" % v) in content @@ -42,7 +43,7 @@ p = os.path.join(parent, 'setup.py') content = open(p).read() # - v = cffi.__version__ + v = cffi.__version__.replace('+', '') assert ("version='%s'" % v) in content def test_c_version(): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit