text: import py, sys, os
  import subprocess, weakref
  from cffi import FFI
  from cffi.backend_ctypes import CTypesBackend
  from testing.support import u
  
  
  SOURCE = """\
  #include <errno.h>
  
  #ifdef _WIN32
  #define EXPORT __declspec(dllexport)
  #else
  #define EXPORT
  #endif
  
  EXPORT int test_getting_errno(void) {
      errno = 123;
      return -1;
  }
  
  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;
  }
  
  EXPORT int my_array[7] = {0, 1, 2, 3, 4, 5, 6};
  
  EXPORT unsigned short foo_2bytes(unsigned short a)
  {
      return (unsigned short)(a + 42);
  }
  EXPORT unsigned int foo_4bytes(unsigned int a)
  {
      return (unsigned int)(a + 42);
  }
  
  EXPORT void modify_struct_value(RECT r)
  {
      r.left = r.right = r.top = r.bottom = 500;
  }
  """
  
  class TestOwnLib(object):
      Backend = CTypesBackend
  
      def setup_class(cls):
          cls.module = None
          from testing.udir import udir
          udir.join('testownlib.c').write(SOURCE)
          if sys.platform == 'win32':
              # did we already build it?
              if cls.Backend is CTypesBackend:
                  dll_path = str(udir) + '\\testownlib1.dll'   # only ascii for the ctypes backend
              else:
                  dll_path = str(udir) + '\\' + (u+'testownlib\u03be.dll')   # non-ascii char
              if os.path.exists(dll_path):
                  cls.module = dll_path
                  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)
                  os.rename(str(udir) + '\\testownlib.dll', dll_path)
                  cls.module = dll_path
          else:
              encoded = None
              if cls.Backend is not CTypesBackend:
                  try:
                      unicode_name = u+'testownlibcaf\xe9'
                      encoded = unicode_name.encode(sys.getfilesystemencoding())
                      if sys.version_info >= (3,):
                          encoded = str(unicode_name)
                  except UnicodeEncodeError:
                      pass
              if encoded is None:
                  unicode_name = u+'testownlib'
                  encoded = str(unicode_name)
              subprocess.check_call(
                  "cc testownlib.c -shared -fPIC -o '%s.so'" % (encoded,),
                  cwd=str(udir), shell=True)
              cls.module = os.path.join(str(udir), unicode_name + (u+'.so'))
          print(repr(cls.module))
  
      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("fails, errno at multiple addresses")
          ffi = FFI(backend=self.Backend())
          ffi.cdef("""
              int test_getting_errno(void);
          """)
          ownlib = ffi.dlopen(self.module)
          res = ownlib.test_getting_errno()
          assert res == -1
          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("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())
          ffi.cdef("""
              int test_setting_errno(void);
          """)
          ownlib = ffi.dlopen(self.module)
          ffi.errno = 42
          res = ownlib.test_setting_errno()
          assert res == 42
          assert ffi.errno == 42
  
      def test_my_array_7(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("""
              extern int my_array[7];
          """)
          ownlib = ffi.dlopen(self.module)
          for i in range(7):
              assert ownlib.my_array[i] == i
          assert len(ownlib.my_array) == 7
          if self.Backend is CTypesBackend:
              py.test.skip("not supported by the ctypes backend")
          ownlib.my_array = list(range(10, 17))
          for i in range(7):
              assert ownlib.my_array[i] == 10 + i
          ownlib.my_array = list(range(7))
          for i in range(7):
              assert ownlib.my_array[i] == i
  
      def test_my_array_no_length(self):
          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")
          ffi = FFI(backend=self.Backend())
          ffi.cdef("""
              extern int my_array[];
          """)
          ownlib = ffi.dlopen(self.module)
          for i in range(7):
              assert ownlib.my_array[i] == i
          py.test.raises(TypeError, len, ownlib.my_array)
          ownlib.my_array = list(range(10, 17))
          for i in range(7):
              assert ownlib.my_array[i] == 10 + i
          ownlib.my_array = list(range(7))
          for i in range(7):
              assert ownlib.my_array[i] == i
  
      def test_keepalive_lib(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("""
              int test_getting_errno(void);
          """)
          ownlib = ffi.dlopen(self.module)
          ffi_r = weakref.ref(ffi)
          ownlib_r = weakref.ref(ownlib)
          func = ownlib.test_getting_errno
          del ffi
          import gc; gc.collect()       # ownlib stays alive
          assert ownlib_r() is not None
          assert ffi_r() is not None    # kept alive by ownlib
          res = func()
          assert res == -1
  
      def test_keepalive_ffi(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("""
              int test_getting_errno(void);
          """)
          ownlib = ffi.dlopen(self.module)
          ffi_r = weakref.ref(ffi)
          ownlib_r = weakref.ref(ownlib)
          func = ownlib.test_getting_errno
          del ownlib
          import gc; gc.collect()       # ffi stays alive
          assert ffi_r() is not None
          assert ownlib_r() is not None # kept alive by ffi
          res = func()
          assert res == -1
          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;
              
              extern 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
  
      def test_addressof_lib(self):
          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 implemented with the ctypes backend")
          ffi = FFI(backend=self.Backend())
          ffi.cdef("extern long left; int test_getting_errno(void);")
          lib = ffi.dlopen(self.module)
          lib.left = 123456
          p = ffi.addressof(lib, "left")
          assert ffi.typeof(p) == ffi.typeof("long *")
          assert p[0] == 123456
          p[0] += 1
          assert lib.left == 123457
          pfn = ffi.addressof(lib, "test_getting_errno")
          assert ffi.typeof(pfn) == ffi.typeof("int(*)(void)")
          assert pfn == lib.test_getting_errno
  
      def test_char16_char32_t(self):
          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 implemented with the ctypes backend")
          ffi = FFI(backend=self.Backend())
          ffi.cdef("""
              char16_t foo_2bytes(char16_t);
              char32_t foo_4bytes(char32_t);
          """)
          lib = ffi.dlopen(self.module)
          assert lib.foo_2bytes(u+'\u1234') == u+'\u125e'
          assert lib.foo_4bytes(u+'\u1234') == u+'\u125e'
          assert lib.foo_4bytes(u+'\U00012345') == u+'\U0001236f'
  
      def test_modify_struct_value(self):
          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("fails with the ctypes backend on some architectures")
          ffi = FFI(backend=self.Backend())
          ffi.cdef("""
              typedef struct {
                  long left;
                  long top;
                  long right;
                  long bottom;
              } RECT;
  
              void modify_struct_value(RECT r);
          """)
          lib = ffi.dlopen(self.module)
          s = ffi.new("RECT *", [11, 22, 33, 44])
          lib.modify_struct_value(s[0])
          assert s.left == 11
          assert s.top == 22
          assert s.right == 33
          assert s.bottom == 44
  
      def test_dlopen_handle(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("uses 'dl' explicitly")
          if self.__class__.Backend is CTypesBackend:
              py.test.skip("not for the ctypes backend")
          backend = self.Backend()
          ffi1 = FFI(backend=backend)
          ffi1.cdef("""void *dlopen(const char *filename, int flags);
                       int dlclose(void *handle);""")
          lib1 = ffi1.dlopen('dl')
          handle = lib1.dlopen(self.module.encode(sys.getfilesystemencoding()),
                               backend.RTLD_LAZY)
          assert ffi1.typeof(handle) == ffi1.typeof("void *")
          assert handle
  
          ffi = FFI(backend=backend)
          ffi.cdef("""unsigned short foo_2bytes(unsigned short a);""")
          lib = ffi.dlopen(handle)
          x = lib.foo_2bytes(1000)
          assert x == 1042
  
          err = lib1.dlclose(handle)
          assert err == 0
  