Commits

Anonymous committed e06a838

Cross Backend Changes

  • Participants
  • Parent commits ecac15a

Comments (0)

Files changed (8)

+import os
 import types
 
 class FFIError(Exception):
         C.printf("hello, %s!\n", ffi.new("char[]", "world"))
     '''
 
-    def __init__(self, backend=None):
+    def __init__(self, backend=None, tmpdir=None):
         """Create an FFI instance.  The 'backend' argument is used to
         select a non-default backend, mostly for tests.
         """
         if backend is None:
             try:
                 import _cffi_backend as backend
+                from cross_backend import update_backend
+                update_backend(backend, tmpdir)
             except ImportError as e:
                 import warnings
                 warnings.warn("import _cffi_backend: %s\n"
         by_size = {}
         for cname in ['long long', 'long', 'int', 'short', 'char']:
             by_size[self.sizeof(cname)] = cname
-        for name, size in self._backend.nonstandard_integer_types().items():
+        nonstandard_integer_types=self._backend.nonstandard_integer_types()
+        for name, size in nonstandard_integer_types.items():
             if size & 0x1000:   # unsigned
                 equiv = 'unsigned %s'
                 size &= ~0x1000

File cffi/cross_backend.py

+import os
+import os.path
+from distutils.core import Extension
+from distutils.core import Distribution
+import distutils.ccompiler
+import distutils.errors
+from .verifier import _caller_dir_pycache
+
+checksrc={
+    'cross_backend/check_int16.c'     : ('int', 2),
+    'cross_backend/check_int64.c'     : ('int', 8),
+    'cross_backend/check_long64.c'    : ('long', 8),
+    'cross_backend/check_intptr_t64.c': ('intptr_t', 8),
+    'cross_backend/check_size_t64.c'  : ('size_t', 8),
+}
+
+type_sizes={
+    'char'   : 1,
+    'short'  : 2,
+    'int'    : 4, #Assume 32bit int unless the cross compile says different
+    'long'   : 4, #Assume 32bit long unless the cross compile says different
+    'long long' : 8,
+    'intptr_t' : 4, #Assume 32bit pointers unless cross compile says different
+    'size_t' : 4, #Assume 32bit pointers unless cross compile says different
+}
+
+
+def initdata(tmpdir):
+    ext = Extension(name='_dummytest', sources=[])
+    dist = Distribution({'ext_modules': [ext]})
+    dist.parse_command_line()
+    try:
+        dist.run_command('build_ext')
+    except (distutils.errors.CompileError,
+            distutils.errors.LinkError) as e:
+        print 'Test builds failed'
+    ddir=os.path.dirname(__file__)
+    cmd_obj = dist.get_command_obj('build_ext')
+    for i in checksrc.keys():
+        try:
+            cmd_obj.compiler.compile([os.path.join(ddir,i)],
+                                     output_dir=cmd_obj.build_temp,
+                                     macros=ext.define_macros[:],
+                                     include_dirs=ext.include_dirs,
+                                     debug=cmd_obj.debug,
+                                     extra_postargs=ext.extra_compile_args or [],
+                                     depends=ext.depends)
+        except:
+            continue
+        type_sizes[checksrc[i][0]]=checksrc[i][1]
+    type_sizes['unsigned char'] = type_sizes['char']
+    type_sizes['unsigned int'] = type_sizes['int']
+    type_sizes['unsigned long'] = type_sizes['long']
+    type_sizes['unsigned long long'] = type_sizes['long long']
+    type_sizes['uintptr_t'] = type_sizes['intptr_t']
+    type_sizes['ssize_t'] = type_sizes['size_t']
+
+
+def nonstandard_integer_types():
+    UNSIGNED = 0x1000
+    x={
+        'int8_t'       : 1,
+        'uint8_t'      : 1 | UNSIGNED,
+        'int16_t'      : 2,
+        'uint16_t'     : 2 | UNSIGNED,
+        'int32_t'      : 4,
+        'uint32_t'     : 4 | UNSIGNED,
+        'int64_t'      : 8,
+        'uint64_t'     : 8 | UNSIGNED,
+        'intptr_t'     : type_sizes['intptr_t'],
+        'uintptr_t'    : type_sizes['intptr_t'] | UNSIGNED,
+        'ptrdiff_t'    : type_sizes['intptr_t'],
+        'size_t'       : type_sizes['size_t'] | UNSIGNED,
+        'ssize_t'      : type_sizes['size_t'],
+    }
+    return x
+
+def sizeof(x):
+    t='%s'%x
+    t=t.split("'")[1]
+    if t in type_sizes:
+        print 'Primitive type size: %s : crossbackend %d cbackend %d'%(t, type_sizes[t], _sizeof(x))
+        return type_sizes[t]
+    return _sizeof(x)
+
+def update_backend(backend, tmpdir):
+    global _sizeof, _module_initialized
+    if not os.environ.get('CFFI_CROSSTARGET', None):
+        return
+    if backend.sizeof == sizeof:
+        return
+    tmpdir = tmpdir or _caller_dir_pycache()
+    print 'Initializing Cross Compiling backend'
+    initdata(tmpdir)
+    backend.nonstandard_integer_types = nonstandard_integer_types
+    _sizeof = backend.sizeof
+    backend.sizeof = sizeof
+

File cffi/cross_backend/check_int16.c

+
+int main() { 
+    static int test_array [1 - 2 * !(sizeof(int) == 2)]; 
+    test_array [0] = 0; 
+    return 0; 
+} 
+

File cffi/cross_backend/check_int64.c

+
+int main() { 
+    static int test_array [1 - 2 * !(sizeof(int) == 8)]; 
+    test_array [0] = 0; 
+    return 0; 
+} 
+

File cffi/cross_backend/check_intptr_t64.c

+#include <stdint.h>
+
+int main() { 
+    static int test_array [1 - 2 * !(sizeof(intptr_t) == 8)]; 
+    test_array [0] = 0; 
+    return 0; 
+} 
+

File cffi/cross_backend/check_long64.c

+
+int main() { 
+    static int test_array [1 - 2 * !(sizeof(long) == 8)]; 
+    test_array [0] = 0; 
+    return 0; 
+} 
+

File cffi/cross_backend/check_size_t64.c

+#include <stddef.h>
+
+int main() { 
+    static int test_array [1 - 2 * !(sizeof(size_t) == 8)]; 
+    test_array [0] = 0; 
+    return 0; 
+} 
+
     description='Foreign Function Interface for Python calling C code.',
     version='0.4',
     packages=['cffi'],
+    package_data={'cffi': ['cross_backend/*']},
     zip_safe=False,
 
     url='http://cffi.readthedocs.org',