From ed54bd467e42e3c34ea170f428671755653711e2 Mon Sep 17 00:00:00 2001
From: Andreas Kloeckner <inform@tiker.net>
Date: Fri, 28 Mar 2014 23:44:40 -0500
Subject: [PATCH] Make cffi branch livable, implement memory pools

---
 TODOs                                      |    8 +
 pyopencl/__init__.py                       |    4 +-
 pyopencl/_cffi.py                          |   27 +-
 {src => pyopencl}/c_wrapper/wrap_cl_core.h |    4 +-
 pyopencl/cffi_cl.py                        |   26 +-
 pyopencl/mempool.py                        |  272 ++
 pyopencl/tools.py                          |   21 +-
 setup.py                                   |   61 +-
 src/c_wrapper/Makefile                     |    6 -
 src/c_wrapper/bitlog.cpp                   |   26 -
 src/c_wrapper/bitlog.hpp                   |   50 -
 src/c_wrapper/wrap_cl.cpp                  | 2350 +++++++-----
 src/wrapper/_pvt_struct_v2.cpp             | 1613 --------
 src/wrapper/_pvt_struct_v3.cpp             | 1749 ---------
 src/wrapper/bitlog.cpp                     |   27 -
 src/wrapper/bitlog.hpp                     |   53 -
 src/wrapper/mempool.hpp                    |  376 --
 src/wrapper/numpy_init.hpp                 |   34 -
 src/wrapper/tools.hpp                      |   43 -
 src/wrapper/wrap_cl.cpp                    |   24 -
 src/wrapper/wrap_cl.hpp                    | 4013 --------------------
 src/wrapper/wrap_cl_part_1.cpp             |  312 --
 src/wrapper/wrap_cl_part_2.cpp             |  359 --
 src/wrapper/wrap_constants.cpp             |  868 -----
 src/wrapper/wrap_helpers.hpp               |  175 -
 src/wrapper/wrap_mempool.cpp               |  290 --
 26 files changed, 1694 insertions(+), 11097 deletions(-)
 create mode 100644 TODOs
 rename {src => pyopencl}/c_wrapper/wrap_cl_core.h (98%)
 create mode 100644 pyopencl/mempool.py
 delete mode 100644 src/c_wrapper/Makefile
 delete mode 100644 src/c_wrapper/bitlog.cpp
 delete mode 100644 src/c_wrapper/bitlog.hpp
 delete mode 100644 src/wrapper/_pvt_struct_v2.cpp
 delete mode 100644 src/wrapper/_pvt_struct_v3.cpp
 delete mode 100644 src/wrapper/bitlog.cpp
 delete mode 100644 src/wrapper/bitlog.hpp
 delete mode 100644 src/wrapper/mempool.hpp
 delete mode 100644 src/wrapper/numpy_init.hpp
 delete mode 100644 src/wrapper/tools.hpp
 delete mode 100644 src/wrapper/wrap_cl.cpp
 delete mode 100644 src/wrapper/wrap_cl.hpp
 delete mode 100644 src/wrapper/wrap_cl_part_1.cpp
 delete mode 100644 src/wrapper/wrap_cl_part_2.cpp
 delete mode 100644 src/wrapper/wrap_constants.cpp
 delete mode 100644 src/wrapper/wrap_helpers.hpp
 delete mode 100644 src/wrapper/wrap_mempool.cpp

diff --git a/TODOs b/TODOs
new file mode 100644
index 00000000..b3b5f4bb
--- /dev/null
+++ b/TODOs
@@ -0,0 +1,8 @@
+- nanny events
+- retry-if-mem-error
+- subdevices
+- Kernel.get_arg_info
+- image/buffer copies
+- interaction with threading BEGIN_ALLOW_THREADS/END_ALLOW_THREADS
+- _pvt_struct
+- Incorporate fixes in C++ stuff from after the fork
diff --git a/pyopencl/__init__.py b/pyopencl/__init__.py
index b9751a66..1f640e33 100644
--- a/pyopencl/__init__.py
+++ b/pyopencl/__init__.py
@@ -524,7 +524,9 @@ def _add_functionality():
                 for i, arg in enumerate(args):
                     self.set_arg(i, arg)
             else:
-                from pyopencl._pvt_struct import pack
+                # TODO:
+                #from pyopencl._pvt_struct import pack
+                from struct import pack
                 for i, (arg, arg_type_char) in enumerate(
                         zip(args, arg_type_chars)):
                     if arg_type_char and arg_type_char != "V":
diff --git a/pyopencl/_cffi.py b/pyopencl/_cffi.py
index fdde752c..977376fa 100644
--- a/pyopencl/_cffi.py
+++ b/pyopencl/_cffi.py
@@ -1,9 +1,5 @@
 from cffi import FFI
 
-import os.path
-current_directory = os.path.dirname(__file__)
-
-
 _ffi = FFI()
 _cl_header = """
 
@@ -93,10 +89,23 @@ typedef struct _cl_buffer_region {
 
 """
 
-with open(os.path.join(current_directory, 'wrap_cl_core.h')) as _f:
-    _wrap_cl_header = _f.read()
 
-_ffi.cdef('%s\n%s' % (_cl_header, _wrap_cl_header))
+def _get_wrap_header():
+    from pkg_resources import Requirement, resource_filename
+    header_name = resource_filename(
+            Requirement.parse("pyopencl"), "pyopencl/c_wrapper/wrap_cl_core.h")
+
+    with open(header_name, "rt") as f:
+        return f.read()
+
+_ffi.cdef(_cl_header + "\n" + _get_wrap_header())
+
+
+def _get_wrapcl_so_name():
+    import os.path
+    current_directory = os.path.dirname(__file__)
+
+    # TODO: cross platform library extension?
+    return os.path.join(current_directory, "_wrapcl.so")
 
-# todo: cross platform library extension?
-_lib = _ffi.dlopen(os.path.join(current_directory, "_wrapcl.so"))
+_lib = _ffi.dlopen(_get_wrapcl_so_name())
diff --git a/src/c_wrapper/wrap_cl_core.h b/pyopencl/c_wrapper/wrap_cl_core.h
similarity index 98%
rename from src/c_wrapper/wrap_cl_core.h
rename to pyopencl/c_wrapper/wrap_cl_core.h
index c279df58..0ad5c337 100644
--- a/src/c_wrapper/wrap_cl_core.h
+++ b/pyopencl/c_wrapper/wrap_cl_core.h
@@ -76,8 +76,8 @@ intptr_t _int_ptr(void*, class_t);
 void* _from_int_ptr(void **ptr_out, intptr_t int_ptr_value, class_t);
 error *_get_info(void *ptr, class_t class_, cl_uint param, generic_info *out);
 void _delete(void *ptr, class_t class_);
-void _free(void*);
-void _free2(void**, uint32_t size);
+void free_pointer(void*);
+void free_pointer_array(void**, uint32_t size);
 
 unsigned bitlog2(unsigned long v);
 
diff --git a/pyopencl/cffi_cl.py b/pyopencl/cffi_cl.py
index 8d450041..094f3e78 100644
--- a/pyopencl/cffi_cl.py
+++ b/pyopencl/cffi_cl.py
@@ -26,7 +26,6 @@ THE SOFTWARE.
 """
 
 
-#from pyopencl._cl import PooledBuffer, MemoryPool
 import warnings
 import np
 import sys
@@ -34,15 +33,12 @@ import sys
 # TODO: can we do without ctypes?
 import ctypes
 
-from _cffi import _ffi, _lib
+from pyopencl._cffi import _ffi, _lib
 
 # are we running on pypy?
 _PYPY = '__pypy__' in sys.builtin_module_names
 
 
-bitlog2 = _lib.bitlog2
-
-
 # {{{ wrapper tools
 
 # {{{ _CArray helper classes
@@ -54,7 +50,7 @@ class _CArray(object):
 
     def __del__(self):
         if self.ptr != _ffi.NULL:
-            _lib._free(self.ptr[0])
+            _lib.free_pointer(self.ptr[0])
 
     def __getitem__(self, key):
         return self.ptr[0].__getitem__(key)
@@ -66,7 +62,7 @@ class _CArray(object):
 
 class _CArrays(_CArray):
     def __del__(self):
-        _lib._free2(_ffi.cast('void**', self.ptr[0]), self.size[0])
+        _lib.free_pointer_array(_ffi.cast('void**', self.ptr[0]), self.size[0])
         super(_CArrays, self).__del__()
 
 # }}}
@@ -99,7 +95,7 @@ def _generic_info_to_python(info):
 
         if type_.endswith(']'):
             ret = map(ci, value)
-            _lib._free(info.value)
+            _lib.free_pointer(info.value)
             return ret
         else:
             return ci(value)
@@ -107,7 +103,7 @@ def _generic_info_to_python(info):
         ret = _ffi.string(value)
     elif type_.startswith('char*['):
         ret = map(_ffi.string, value)
-        _lib._free2(info.value, len(value))
+        _lib.free_pointer_array(info.value, len(value))
     elif type_.endswith(']'):
         if type_.startswith('char['):
             ret = ''.join(a[0] for a in value)
@@ -124,7 +120,7 @@ def _generic_info_to_python(info):
     else:
         ret = value[0]
     if info.dontfree == 0:
-        _lib._free(info.value)
+        _lib.free_pointer(info.value)
     return ret
 
 # }}}
@@ -273,8 +269,8 @@ def _handle_error(error):
         # non-pyopencl exceptions are handled here
         import exceptions
         e = exceptions.RuntimeError(_ffi.string(error.msg))
-        _lib._free(error.msg)
-        _lib._free(error)
+        _lib.free_pointer(error.msg)
+        _lib.free_pointer(error)
         raise e
     if error.code == status_code.MEM_OBJECT_ALLOCATION_FAILURE:
         klass = MemoryError
@@ -286,9 +282,9 @@ def _handle_error(error):
         klass = Error
     e = klass(routine=_ffi.string(error.routine),
             code=error.code, msg=_ffi.string(error.msg))
-    _lib._free(error.routine)
-    _lib._free(error.msg)
-    _lib._free(error)
+    _lib.free_pointer(error.routine)
+    _lib.free_pointer(error.msg)
+    _lib.free_pointer(error)
     raise e
 
 # }}}
diff --git a/pyopencl/mempool.py b/pyopencl/mempool.py
new file mode 100644
index 00000000..38c10562
--- /dev/null
+++ b/pyopencl/mempool.py
@@ -0,0 +1,272 @@
+from __future__ import division
+
+__copyright__ = """
+Copyright (C) 2014 Andreas Kloeckner
+"""
+
+__license__ = """
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+"""
+
+
+import numpy as np
+import pyopencl as cl
+
+
+# {{{ allocators
+
+class AllocatorBase(object):
+    def __call__(self, nbytes):
+        try_count = 0
+
+        while try_count < 2:
+            try:
+                return self.allocate(nbytes)
+            except cl.Error, e:
+                if not e.is_out_of_memory():
+                    raise
+                try_count += 1
+                if try_count == 2:
+                    raise
+
+            self.try_release_blocks()
+
+    def try_release_blocks(self):
+        import gc
+        gc.collect()
+
+
+class DeferredAllocator(AllocatorBase):
+    is_deferred = True
+
+    def __init__(self, context, mem_flags=cl.mem_flags.READ_WRITE):
+        self.context = context
+        self.mem_flags = mem_flags
+
+    def allocate(self, nbytes):
+        return cl.Buffer(self.context, self.mem_flags, nbytes)
+
+
+_zero = np.array([0, 0, 0, 0], dtype=np.int8)
+
+
+class ImmediateAllocator(AllocatorBase):
+    is_deferred = False
+
+    def __init__(self, queue, mem_flags=cl.mem_flags.READ_WRITE):
+        self.context = queue.context
+        self.queue = queue
+        self.mem_flags = mem_flags
+
+    def allocate(self, nbytes):
+        buf = cl.Buffer(self.context, self.mem_flags, nbytes)
+
+        # Make sure the buffer gets allocated right here and right now.
+        # This looks (and is) expensive. But immediate allocators
+        # have their main use in memory pools, whose basic assumption
+        # is that allocation is too expensive anyway--but they rely
+        # on exact 'out-of-memory' information.
+
+        from pyopencl.cffi_cl import _enqueue_write_buffer
+        _enqueue_write_buffer(
+                self.queue, buf,
+                _zero[:min(len(_zero), nbytes)],
+                is_blocking=False)
+
+        # No need to wait for completion here. clWaitForEvents (e.g.)
+        # cannot return mem object allocation failures. This implies that
+        # the buffer is faulted onto the device on enqueue.
+
+        return buf
+
+# }}}
+
+
+# {{{ memory pool
+
+class MemoryPool(object):
+    mantissa_bits = 2
+    mantissa_mask = (1 << mantissa_bits) - 1
+
+    def __init__(self, allocator):
+        self.allocator = allocator
+
+        self.bin_nr_to_bin = {}
+
+        if self.allocator.is_deferred:
+            from warnings import warn
+            warn("Memory pools expect non-deferred "
+                    "semantics from their allocators. You passed a deferred "
+                    "allocator, i.e. an allocator whose allocations can turn out to "
+                    "be unavailable long after allocation.", statcklevel=2)
+
+        self.active_blocks = 0
+
+    @classmethod
+    def bin_number(cls, size):
+        l = max(size.bit_length(), 1) - 1
+
+        mantissa_bits = cls.mantissa_bits
+        if l >= mantissa_bits:
+            shifted = size >> (l - mantissa_bits)
+        else:
+            shifted = size << (mantissa_bits - l)
+
+        assert not (size and (shifted & (1 << mantissa_bits)) == 0)
+
+        chopped = shifted & cls.mantissa_mask
+
+        return l << mantissa_bits | chopped
+
+    @classmethod
+    def alloc_size(cls, bin_nr):
+        mantissa_bits = cls.mantissa_bits
+
+        exponent = bin_nr >> mantissa_bits
+        mantissa = bin_nr & cls.mantissa_mask
+
+        exp_minus_mbits = exponent-mantissa_bits
+        if exp_minus_mbits >= 0:
+            ones = (1 << exp_minus_mbits) - 1
+            head = ((1 << mantissa_bits) | mantissa) << exp_minus_mbits
+        else:
+            ones = 0
+            head = ((1 << mantissa_bits) | mantissa) >> -exp_minus_mbits
+
+        assert not (ones & head)
+        return head | ones
+
+    def allocate(self):
+        pass
+
+    __call__ = allocate
+
+    def stop_holding(self):
+        self.stop_holding = True
+        self.free_held()
+
+    def free_held(self):
+        for bin_nr, bin_list in self.bin_nr_to_bin.iteritems():
+            while bin_list:
+                self.allocator.free(bin_list.pop())
+
+    @property
+    def held_blocks(self):
+        return sum(
+                len(bin_list)
+                for bin_list in self.bin_nr_to_bin.itervalues())
+
+    def allocate(self, size):
+        bin_nr = self.bin_number(size)
+        bin_list = self.bin_nr_to_bin.setdefault(bin_nr, [])
+
+        if bin_list:
+            # if (m_trace)
+            #   std::cout
+            #     << "[pool] allocation of size " << size
+            #     << " served from bin " << bin_nr
+            #     << " which contained " << bin_list.size()
+            #     << " entries" << std::endl;
+            self.active_blocks += 1
+            return bin_list.pop()
+
+        alloc_sz = self.alloc_size(bin_nr)
+
+        assert self.bin_number(alloc_sz) == bin_nr
+
+        # if (m_trace)
+        #   std::cout << "[pool] allocation of size " << size
+        #   << " required new memory" << std::endl;
+
+        try:
+            result = self.allocator(alloc_sz)
+            self.active_blocks += 1
+            return result
+        except cl.MemoryError:
+            pass
+
+        # if (m_trace)
+        #   std::cout << "[pool] allocation triggered OOM, running GC" << std::endl;
+
+        self.allocator.try_release_blocks()
+
+        if bin_list:
+            return bin_list.pop()
+
+        # if (m_trace)
+        #   std::cout << "[pool] allocation still OOM after GC" << std::endl;
+
+        for _ in self._try_to_free_memory():
+            try:
+                result = self.allocator(alloc_sz)
+                self.active_blocks += 1
+                return result
+            except cl.MemoryError:
+                pass
+
+        raise cl.MemoryError(
+                "failed to free memory for allocation",
+                routine="memory_pool::allocate",
+                code=cl.status_code.MEM_OBJECT_ALLOCATION_FAILURE)
+
+    def free(self, buf, size):
+        self.active_blocks -= 1
+        bin_nr = self.bin_number(size)
+
+        if not self.stop_holding:
+            self.bin_nr_to_bin.setdefault(bin_nr, []).append(buf)
+
+            # if (m_trace)
+            #   std::cout << "[pool] block of size " << size << " returned to bin "
+            #     << bin_nr << " which now contains " << get_bin(bin_nr).size()
+            #     << " entries" << std::endl;
+        else:
+            self.allocator.free(buf)
+
+    def _try_to_free_memory(self):
+        for bin_nr, bin_list in self.bin_nr_to_bin.iteritems():
+            while bin_list:
+                self.allocator.free(bin_list.pop())
+                self.held_blocks -= 1
+                yield
+
+
+class PooledBuffer(cl.MemoryObjectHolder):
+    _id = 'buffer'
+
+    def __init__(self, pool, buf, size):
+        self.pool = pool
+        self.buf = buf
+        self.ptr = buf.ptr
+        self.size = size
+
+    def release(self):
+        self.pool.free(self.buf, self.size)
+        self.buf = None
+        self.ptr = None
+
+    def __del__(self):
+        if self.buf is not None:
+            self.release()
+
+# }}}
+
+
+
+# vim: foldmethod=marker
diff --git a/pyopencl/tools.py b/pyopencl/tools.py
index 553eb064..5c65edc3 100644
--- a/pyopencl/tools.py
+++ b/pyopencl/tools.py
@@ -60,25 +60,8 @@ _register_types()
 
 # {{{ imported names
 
-bitlog2 = cl.bitlog2
-
-PooledBuffer = cl.PooledBuffer
-
-from pyopencl._cl import _tools_DeferredAllocator as DeferredAllocator
-from pyopencl._cl import (  # noqa
-        _tools_ImmediateAllocator as ImmediateAllocator)
-
-
-class CLAllocator(DeferredAllocator):
-    def __init__(self, *args, **kwargs):
-        from warnings import warn
-        warn("pyopencl.tools.CLAllocator is deprecated. "
-                "It will be continue to exist throughout the 2013.x "
-                "versions of PyOpenCL. Use {Deferred,Immediate}Allocator.",
-                DeprecationWarning, 2)
-        DeferredAllocator.__init__(self, *args, **kwargs)
-
-MemoryPool = cl.MemoryPool
+from pyopencl.mempool import (  # noqa
+        PooledBuffer, DeferredAllocator, ImmediateAllocator, MemoryPool)
 
 # }}}
 
diff --git a/setup.py b/setup.py
index 1a6c3733..26fb709b 100644
--- a/setup.py
+++ b/setup.py
@@ -1,13 +1,40 @@
 #!/usr/bin/env python
 # -*- coding: latin-1 -*-
 
+__copyright__ = """
+Copyright (C) 2009-14 Andreas Kloeckner
+Copyright (C) 2013 Marko Bencun
+"""
+
+__license__ = """
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+"""
+
+
+import sys
+
 
 def get_config_schema():
     from aksetup_helper import ConfigSchema, Option, \
             IncludeDir, LibraryDir, Libraries, \
             Switch, StringListOption
 
-    import sys
     if 'darwin' in sys.platform:
         import platform
         osx_ver, _, _ = platform.mac_ver()
@@ -146,23 +173,15 @@ def main():
         from aksetup_helper import count_down_delay
         count_down_delay(delay=5)
 
-    import sys
-    if sys.version_info >= (3,):
-        pvt_struct_source = "src/wrapper/_pvt_struct_v3.cpp"
-    else:
-        pvt_struct_source = "src/wrapper/_pvt_struct_v2.cpp"
-
-    # wrap_cl_core.h needs to be available in pyopencl/
-    # the cffi verifier depends on it.
-    import shutil
-    shutil.copyfile("src/c_wrapper/wrap_cl_core.h", "pyopencl/wrap_cl_core.h")
-
     # from pyopencl._cffi import _get_verifier
-    # import os.path
-    # current_directory = os.path.dirname(__file__)
 
-    # # for development: clean cache such that the extension is rebuilt
-    # shutil.rmtree(os.path.join(current_directory, 'pyopencl', '__pycache__/'), ignore_errors=True)
+    # for development: clean cache such that the extension is rebuilt
+    if 0:
+        import os.path
+        current_directory = os.path.dirname(__file__)
+
+        shutil.rmtree(os.path.join(current_directory,
+            'pyopencl', '__pycache__/'), ignore_errors=True)
 
     setup(name="pyopencl",
             # metadata
@@ -213,9 +232,12 @@ def main():
                                ["src/c_wrapper/wrap_cl.cpp",
                                 "src/c_wrapper/wrap_constants.cpp",
                                 #"src/c_wrapper/wrap_mempool.cpp",
-                                "src/c_wrapper/bitlog.cpp",
                                 ],
-                               include_dirs=conf["CL_INC_DIR"] + ["src/c_wrapper/"],
+                               include_dirs=(
+                                   conf["CL_INC_DIR"]
+                                   + ["src/c_wrapper/"]
+                                   + ["pyopencl/c_wrapper/"]
+                                   ),
                                library_dirs=conf["CL_LIB_DIR"],
                                libraries=conf["CL_LIBNAME"],
                                define_macros=list(EXTRA_DEFINES.items()),
@@ -228,8 +250,7 @@ def main():
                     "pyopencl": [
                         "cl/*.cl",
                         "cl/*.h",
-                        "wrap_cl_core.h",
-                        "_cl.so",
+                        "c_wrapper/wrap_cl_core.h",
                         ]
                     },
 
diff --git a/src/c_wrapper/Makefile b/src/c_wrapper/Makefile
deleted file mode 100644
index 7424e5de..00000000
--- a/src/c_wrapper/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-all:
-	g++ -c -Wall -DHAVE_GL=1 -DPYOPENCL_PRETEND_CL_VERSION=4112 -fpic wrap_cl.cpp wrap_constants.cpp bitlog.cpp
-	#g++ -c -Wall -DPYOPENCL_PRETEND_CL_VERSION=4112 -fpic wrap_cl.cpp wrap_constants.cpp bitlog.cpp
-	g++ -shared -o libwrapcl.so wrap_cl.o wrap_constants.o bitlog.o
-	cp libwrapcl.so ../../pyopencl/
-	cp wrap_cl_core.h ../../pyopencl/wrap_cl_core.h
diff --git a/src/c_wrapper/bitlog.cpp b/src/c_wrapper/bitlog.cpp
deleted file mode 100644
index 67b82511..00000000
--- a/src/c_wrapper/bitlog.cpp
+++ /dev/null
@@ -1,26 +0,0 @@
-#include "bitlog.hpp"
-
-
-
-/* from http://graphics.stanford.edu/~seander/bithacks.html */
-const char pyopencl::log_table_8[] =
-{
-  0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
-  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
-};
-
-
diff --git a/src/c_wrapper/bitlog.hpp b/src/c_wrapper/bitlog.hpp
deleted file mode 100644
index 86e11710..00000000
--- a/src/c_wrapper/bitlog.hpp
+++ /dev/null
@@ -1,50 +0,0 @@
-// Base-2 logarithm bithack.
-
-
-
-
-#ifndef _AFJDFJSDFSD_PYOPENCL_HEADER_SEEN_BITLOG_HPP
-#define _AFJDFJSDFSD_PYOPENCL_HEADER_SEEN_BITLOG_HPP
-
-
-
-
-#include <climits>
-#include <stdint.h>
-
-namespace pyopencl
-{
-  extern const char log_table_8[];
-
-  inline unsigned bitlog2_16(uint16_t v)
-  {
-    if (unsigned long t = v >> 8)
-      return 8+log_table_8[t];
-    else 
-      return log_table_8[v];
-  }
-
-  inline unsigned bitlog2_32(uint32_t v)
-  {
-    if (uint16_t t = v >> 16)
-      return 16+bitlog2_16(t);
-    else 
-      return bitlog2_16(v);
-  }
-
-  inline unsigned bitlog2(unsigned long v)
-  {
-#if (ULONG_MAX != 4294967295)
-    if (uint32_t t = v >> 32)
-      return 32+bitlog2_32(t);
-    else 
-#endif
-      return bitlog2_32(v);
-  }
-}
-
-
-
-
-
-#endif
diff --git a/src/c_wrapper/wrap_cl.cpp b/src/c_wrapper/wrap_cl.cpp
index 97568cc1..4d976d86 100644
--- a/src/c_wrapper/wrap_cl.cpp
+++ b/src/c_wrapper/wrap_cl.cpp
@@ -6,11 +6,33 @@
 #include <string.h>
 #include <memory>
 #include <sstream>
-#include "bitlog.hpp"
 
 #define MALLOC(TYPE, VAR, N) TYPE *VAR = reinterpret_cast<TYPE*>(malloc(sizeof(TYPE)*(N)));
 
+
 // {{{ tracing and error reporting
+
+#define BEGIN_C_HANDLE_ERROR try {
+#define END_C_HANDLE_ERROR \
+    } \
+    catch(const pyopencl::error& e) \
+    {               \
+      MALLOC(::error, error, 1); \
+      error->routine = pyopencl::_copy_str(e.routine()); \
+      error->msg = pyopencl::_copy_str(e.what()); \
+      error->code = e.code(); \
+      error->other = 0; \
+      return error; \
+    } \
+    catch(const std::exception& e) \
+    { \
+      /* non-pyopencl exceptions need to be converted as well */ \
+      MALLOC(::error, error, 1); \
+      error->other = 1; \
+      error->msg = pyopencl::_copy_str(e.what()); \
+      return error; \
+    }
+
 #ifdef PYOPENCL_TRACE
 #define PYOPENCL_PRINT_CALL_TRACE(NAME)         \
   std::cerr << NAME << std::endl;
@@ -21,26 +43,6 @@
 #define PYOPENCL_PRINT_CALL_TRACE_INFO(NAME, EXTRA_INFO) /*nothing*/
 #endif
 
-#define C_HANDLE_ERROR(OPERATION)                       \
-  try {                                                 \
-    OPERATION                                           \
-      } catch(const pyopencl::error& e) {               \
-    MALLOC(::error, error, 1);                          \
-    error->routine = pyopencl::_copy_str(e.routine());  \
-    error->msg = pyopencl::_copy_str(e.what());         \
-    error->code = e.code();                             \
-    error->other = 0;                                   \
-    return error;                                       \
-  } catch(const std::exception& e) {                    \
-    /* non-pyopencl exceptions shall be */              \
-    /* converted as well */                             \
-    MALLOC(::error, error, 1);                          \
-    error->other = 1;                                   \
-    error->msg = pyopencl::_copy_str(e.what());         \
-    return error;                                       \
-  }                                                     \
-
-
 // TODO Py_BEGIN_ALLOW_THREADS \ Py_END_ALLOW_THREADS below
 #define PYOPENCL_CALL_GUARDED_THREADED(NAME, ARGLIST)   \
   {                                                     \
@@ -77,31 +79,32 @@
 
 // }}}
 
+
+// {{{ extension function pointers
+
 #if PYOPENCL_CL_VERSION >= 0x1020
 
-#define PYOPENCL_GET_EXT_FUN(PLATFORM, NAME, VAR)                       \
-  NAME##_fn VAR                                                         \
-  = (NAME##_fn)                                                         \
-                                         clGetExtensionFunctionAddressForPlatform(PLATFORM, #NAME); \
-                                                                        \
-  if (!VAR)                                                             \
-    throw error(#NAME, CL_INVALID_VALUE, #NAME                          \
-                "not available");
+#define PYOPENCL_GET_EXT_FUN(PLATFORM, NAME, VAR) \
+  NAME##_fn VAR  = (NAME##_fn) \
+      clGetExtensionFunctionAddressForPlatform(PLATFORM, #NAME); \
+  \
+  if (!VAR) \
+    throw error(#NAME, CL_INVALID_VALUE, #NAME " not available");
 
 #else
 
-#define PYOPENCL_GET_EXT_FUN(PLATFORM, NAME, VAR)                       \
-  NAME##_fn VAR                                                         \
-  = (NAME##_fn)                                                         \
-                                         clGetExtensionFunctionAddress(#NAME); \
-                                                                        \
-  if (!VAR)                                                             \
-    throw error(#NAME, CL_INVALID_VALUE, #NAME                          \
-                "not available");
+#define PYOPENCL_GET_EXT_FUN(PLATFORM, NAME, VAR) \
+  NAME##_fn VAR = (NAME##_fn) clGetExtensionFunctionAddress(#NAME); \
+  \
+  if (!VAR) \
+    throw error(#NAME, CL_INVALID_VALUE, #NAME " not available");
 
 #endif
 
+// }}}
+
 
+// {{{ GetInfo helpers
 
 #define PYOPENCL_GET_VEC_INFO(WHAT, FIRST_ARG, SECOND_ARG, RES_VEC)     \
   {                                                                     \
@@ -193,7 +196,11 @@
     return info;                                                        \
   }
 
-// {{{ event helpers --------------------------------------------------------------
+// }}}
+
+
+// {{{ event helpers
+
 #define PYOPENCL_PARSE_OBJECT_LIST(CLS, TYPE, OUT, NAME, NUM)   \
   std::vector<TYPE> OUT((NUM));                                 \
   {                                                             \
@@ -209,7 +216,7 @@
   num_wait_for, event_wait_list.empty( ) ? NULL : &event_wait_list.front()
 
 
-#define PYOPENCL_RETURN_NEW_EVENT(evt)          \
+#define PYOPENCL_RETURN_NEW_EVENT(evt) \
   try                                           \
     {                                           \
       return new event(evt, false);             \
@@ -222,61 +229,67 @@
 
 // }}}
 
+
 // {{{ equality testing
-#define PYOPENCL_EQUALITY_TESTS(cls)            \
-  bool operator==(cls const &other) const       \
-  { return data() == other.data(); }            \
-  bool operator!=(cls const &other) const       \
-  { return data() != other.data(); }            \
-  long hash() const                             \
+
+#define PYOPENCL_EQUALITY_TESTS(cls) \
+  \
+  bool operator==(cls const &other) const \
+  { return data() == other.data(); } \
+  \
+  bool operator!=(cls const &other) const \
+  { return data() != other.data(); } \
+  \
+  long hash() const \
   { return (long) (intptr_t) data(); }
-// }}}
 
+// }}}
 
 
 // {{{ tools
+
 #define PYOPENCL_CAST_BOOL(B) ((B) ? CL_TRUE : CL_FALSE)
 
-#define PYOPENCL_PARSE_PY_DEVICES                                       \
-  std::vector<cl_device_id> devices_vec;                                \
-  cl_uint num_devices;                                                  \
-  cl_device_id *devices;                                                \
-                                                                        \
+#define PYOPENCL_PARSE_PY_DEVICES \
+  std::vector<cl_device_id> devices_vec; \
+  cl_uint num_devices; \
+  cl_device_id *devices; \
+  \
   if (py_devices.ptr() == Py_None)                                      \
     {                                                                   \
-      num_devices = 0;                                                  \
-      devices = 0;                                                      \
+      num_devices = 0; \
+      devices = 0; \
     }                                                                   \
   else                                                                  \
     {                                                                   \
       PYTHON_FOREACH(py_dev, py_devices)                                \
         devices_vec.push_back(                                          \
-                              py::extract<device &>(py_dev)().data());  \
-      num_devices = devices_vec.size();                                 \
-      devices = devices_vec.empty( ) ? NULL : &devices_vec.front();     \
+                              py::extract<device &>(py_dev)().data()); \
+      num_devices = devices_vec.size(); \
+      devices = devices_vec.empty( ) ? NULL : &devices_vec.front(); \
     }                                                                   \
 
 
 
-#define PYOPENCL_RETRY_IF_MEM_ERROR(OPERATION)  \
-  {                                             \
+#define PYOPENCL_RETRY_IF_MEM_ERROR(OPERATION) \
+  { \
     bool failed_with_mem_error = false;         \
     try                                         \
-      {                                         \
-        OPERATION                               \
-          }                                     \
+    {                                         \
+      OPERATION                               \
+    }                                     \
     catch (pyopencl::error &e)                  \
-      {                                         \
-        failed_with_mem_error = true;           \
-        if (!e.is_out_of_memory())              \
-          throw;                                \
-      }                                         \
+    {                                         \
+      failed_with_mem_error = true;           \
+      if (!e.is_out_of_memory())              \
+        throw;                                \
+    }                                         \
                                                 \
     if (failed_with_mem_error)                  \
-      {                                         \
-    /* If we get here, we got an error from CL.
-     * We should run the Python GC to try and free up
-     * some memory references. */                       \
+    {                                         \
+      /* If we get here, we got an error from CL.
+       * We should run the Python GC to try and free up
+       * some memory references. */                       \
 run_python_gc();                                \
 \
 /* Now retry the allocation. If it fails again,
@@ -290,6 +303,8 @@ run_python_gc();                                \
 // }}}
 
 
+// {{{ more odds and ends
+
 #define SWITCHCLASS(OPERATION)                                          \
   switch(class_) {                                                      \
   case ::CLASS_PLATFORM: OPERATION(PLATFORM, platform); break;          \
@@ -321,12 +336,15 @@ run_python_gc();                                \
 #define PYOPENCL_CL_SAMPLER cl_sampler
 
 template<class T>
-std::string tostring(const T& v) {
-std::ostringstream ostr;
- ostr << v;
- return ostr.str();
+std::string tostring(const T& v)
+{
+  std::ostringstream ostr;
+  ostr << v;
+  return ostr.str();
 }
 
+// }}}
+
 
 namespace pyopencl
 {
@@ -337,86 +355,99 @@ namespace pyopencl
     return cstr;
   }
 
-  // {{{ error
-  class error : public std::runtime_error
-  {
-  private:
-    const char *m_routine;
-    cl_int m_code;
-
-  public:
-    error(const char *rout, cl_int c, const char *msg="")
-      : std::runtime_error(msg), m_routine(rout), m_code(c)
-    { std::cout << rout <<";" << msg<< ";" << c << std::endl; }
-    const char *routine() const
-    {
-      return m_routine;
-    }
+  class noncopyable {
+    // non-copyable
 
-    cl_int code() const
-    {
-      return m_code;
-    }
+    private:
+      noncopyable(noncopyable const &)
+      { }
 
-    bool is_out_of_memory() const
-    {
-      return (code() == CL_MEM_OBJECT_ALLOCATION_FAILURE
-              || code() == CL_OUT_OF_RESOURCES
-              || code() == CL_OUT_OF_HOST_MEMORY);
-    }
+      noncopyable &operator=(noncopyable const &)
+      {
+        return *this;
+      }
 
+    public:
+      noncopyable()
+      { }
   };
 
-  // }}}
 
+  // {{{ error
+
+  class error : public std::runtime_error
+  {
+    private:
+      const char *m_routine;
+      cl_int m_code;
+
+    public:
+      error(const char *rout, cl_int c, const char *msg="")
+        : std::runtime_error(msg), m_routine(rout), m_code(c)
+        { std::cout << rout <<";" << msg<< ";" << c << std::endl; }
+      const char *routine() const
+      {
+        return m_routine;
+      }
 
-  //#define MAKE_INFO(name, type, value) {  }
+      cl_int code() const
+      {
+        return m_code;
+      }
 
-  class _common {
+      bool is_out_of_memory() const
+      {
+        return (code() == CL_MEM_OBJECT_ALLOCATION_FAILURE
+            || code() == CL_OUT_OF_RESOURCES
+            || code() == CL_OUT_OF_HOST_MEMORY);
+      }
   };
 
+  // }}}
+
 
   // {{{ platform
-  class platform : public _common
+
+  class platform : public noncopyable
   {
-  private:
-    cl_platform_id m_platform;
+    private:
+      cl_platform_id m_platform;
 
-  public:
-    platform(cl_platform_id pid)
-      : m_platform(pid)
-    { }
+    public:
+      platform(cl_platform_id pid)
+        : m_platform(pid)
+      { }
 
-    platform(cl_platform_id pid, bool /*retain (ignored)*/)
-      : m_platform(pid)
-    { }
+      platform(cl_platform_id pid, bool /*retain (ignored)*/)
+        : m_platform(pid)
+      { }
 
-    cl_platform_id data() const
-    {
-      return m_platform;
-    }
+      cl_platform_id data() const
+      {
+        return m_platform;
+      }
 
-    PYOPENCL_EQUALITY_TESTS(platform);
+      PYOPENCL_EQUALITY_TESTS(platform);
 
-    generic_info get_info(cl_platform_info param_name) const
-    {
-      switch (param_name)
+      generic_info get_info(cl_platform_info param_name) const
+      {
+        switch (param_name)
         {
-        case CL_PLATFORM_PROFILE:
-        case CL_PLATFORM_VERSION:
-        case CL_PLATFORM_NAME:
-        case CL_PLATFORM_VENDOR:
+          case CL_PLATFORM_PROFILE:
+          case CL_PLATFORM_VERSION:
+          case CL_PLATFORM_NAME:
+          case CL_PLATFORM_VENDOR:
 #if !(defined(CL_PLATFORM_NVIDIA) && CL_PLATFORM_NVIDIA == 0x3001)
-        case CL_PLATFORM_EXTENSIONS:
+          case CL_PLATFORM_EXTENSIONS:
 #endif
-          PYOPENCL_GET_STR_INFO(Platform, m_platform, param_name);
+            PYOPENCL_GET_STR_INFO(Platform, m_platform, param_name);
 
-        default:
-          throw error("Platform.get_info", CL_INVALID_VALUE);
+          default:
+            throw error("Platform.get_info", CL_INVALID_VALUE);
         }
-    }
+      }
 
-    std::vector<cl_device_id> get_devices(cl_device_type devtype);
+      std::vector<cl_device_id> get_devices(cl_device_type devtype);
   };
 
 
@@ -439,47 +470,50 @@ namespace pyopencl
 
   // }}}
 
+
   // {{{ device
-  class device : public _common // : boost::noncopyable
+
+  class device : public noncopyable
   {
-  public:
-    enum reference_type_t {
-      REF_NOT_OWNABLE,
-      REF_FISSION_EXT,
+    public:
+      enum reference_type_t {
+        REF_NOT_OWNABLE,
+        REF_FISSION_EXT,
 #if PYOPENCL_CL_VERSION >= 0x1020
-      REF_CL_1_2,
+        REF_CL_1_2,
 #endif
-    };
-  private:
-    cl_device_id m_device;
-    reference_type_t m_ref_type;
+      };
 
-  public:
-    device(cl_device_id did)
-      : m_device(did), m_ref_type(REF_NOT_OWNABLE)
-    { }
+    private:
+      cl_device_id m_device;
+      reference_type_t m_ref_type;
 
-    device(cl_device_id did, bool retain, reference_type_t ref_type=REF_NOT_OWNABLE)
-      : m_device(did), m_ref_type(ref_type)
-    {
-      if (retain && ref_type != REF_NOT_OWNABLE)
+    public:
+      device(cl_device_id did)
+        : m_device(did), m_ref_type(REF_NOT_OWNABLE)
+      { }
+
+      device(cl_device_id did, bool retain, reference_type_t ref_type=REF_NOT_OWNABLE)
+        : m_device(did), m_ref_type(ref_type)
+      {
+        if (retain && ref_type != REF_NOT_OWNABLE)
         {
           if (false)
-            { }
+          { }
 #if (defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION))
           else if (ref_type == REF_FISSION_EXT)
-            {
+          {
 #if PYOPENCL_CL_VERSION >= 0x1020
-              cl_platform_id plat;
-              PYOPENCL_CALL_GUARDED(clGetDeviceInfo, (m_device, CL_DEVICE_PLATFORM,
-                                                      sizeof(plat), &plat, NULL));
+            cl_platform_id plat;
+            PYOPENCL_CALL_GUARDED(clGetDeviceInfo, (m_device, CL_DEVICE_PLATFORM,
+                  sizeof(plat), &plat, NULL));
 #endif
 
-              PYOPENCL_GET_EXT_FUN(plat,
-                                   clRetainDeviceEXT, retain_func);
+            PYOPENCL_GET_EXT_FUN(plat,
+                clRetainDeviceEXT, retain_func);
 
-              PYOPENCL_CALL_GUARDED(retain_func, (did));
-            }
+            PYOPENCL_CALL_GUARDED(retain_func, (did));
+          }
 #endif
 
 #if PYOPENCL_CL_VERSION >= 0x1020
@@ -493,189 +527,189 @@ namespace pyopencl
             throw error("Device", CL_INVALID_VALUE,
                         "cannot own references to devices when device fission or CL 1.2 is not available");
         }
-    }
+      }
 
-    ~device()
-    {
-      if (false)
+      ~device()
+      {
+        if (false)
         { }
 #if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION)
-      else if (m_ref_type == REF_FISSION_EXT)
+        else if (m_ref_type == REF_FISSION_EXT)
         {
 #if PYOPENCL_CL_VERSION >= 0x1020
           cl_platform_id plat;
           PYOPENCL_CALL_GUARDED(clGetDeviceInfo, (m_device, CL_DEVICE_PLATFORM,
-                                                  sizeof(plat), &plat, NULL));
+                sizeof(plat), &plat, NULL));
 #endif
 
           PYOPENCL_GET_EXT_FUN(plat,
-                               clReleaseDeviceEXT, release_func);
+              clReleaseDeviceEXT, release_func);
 
           PYOPENCL_CALL_GUARDED_CLEANUP(release_func, (m_device));
         }
 #endif
 
 #if PYOPENCL_CL_VERSION >= 0x1020
-      else if (m_ref_type == REF_CL_1_2)
-        PYOPENCL_CALL_GUARDED(clReleaseDevice, (m_device));
+        else if (m_ref_type == REF_CL_1_2)
+          PYOPENCL_CALL_GUARDED(clReleaseDevice, (m_device));
 #endif
-    }
+      }
 
-    cl_device_id data() const
-    {
-      return m_device;
-    }
+      cl_device_id data() const
+      {
+        return m_device;
+      }
 
-    PYOPENCL_EQUALITY_TESTS(device);
+      PYOPENCL_EQUALITY_TESTS(device);
 
-    generic_info get_info(cl_device_info param_name) const
-    {
+      generic_info get_info(cl_device_info param_name) const
+      {
 #define DEV_GET_INT_INF(TYPE) PYOPENCL_GET_INTEGRAL_INFO(Device, m_device, param_name, TYPE);
 
-      switch (param_name)
-        {
-        case CL_DEVICE_TYPE: DEV_GET_INT_INF(cl_device_type);
-        case CL_DEVICE_VENDOR_ID: DEV_GET_INT_INF(cl_uint);
-        case CL_DEVICE_MAX_COMPUTE_UNITS: DEV_GET_INT_INF(cl_uint);
-        case CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS: DEV_GET_INT_INF(cl_uint);
-        case CL_DEVICE_MAX_WORK_GROUP_SIZE: DEV_GET_INT_INF(size_t);
-
-        case CL_DEVICE_MAX_WORK_ITEM_SIZES:
+        switch (param_name)
           {
-            std::vector<size_t> result;
-            PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result);
-            PYOPENCL_GET_ARRAY_INFO(size_t, result);
-          }
+          case CL_DEVICE_TYPE: DEV_GET_INT_INF(cl_device_type);
+          case CL_DEVICE_VENDOR_ID: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_MAX_COMPUTE_UNITS: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_MAX_WORK_GROUP_SIZE: DEV_GET_INT_INF(size_t);
 
-        case CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR: DEV_GET_INT_INF(cl_uint);
-        case CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT: DEV_GET_INT_INF(cl_uint);
-        case CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT: DEV_GET_INT_INF(cl_uint);
-        case CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG: DEV_GET_INT_INF(cl_uint);
-        case CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT: DEV_GET_INT_INF(cl_uint);
-        case CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE: DEV_GET_INT_INF(cl_uint);
-
-        case CL_DEVICE_MAX_CLOCK_FREQUENCY: DEV_GET_INT_INF(cl_uint);
-        case CL_DEVICE_ADDRESS_BITS: DEV_GET_INT_INF(cl_uint);
-        case CL_DEVICE_MAX_READ_IMAGE_ARGS: DEV_GET_INT_INF(cl_uint);
-        case CL_DEVICE_MAX_WRITE_IMAGE_ARGS: DEV_GET_INT_INF(cl_uint);
-        case CL_DEVICE_MAX_MEM_ALLOC_SIZE: DEV_GET_INT_INF(cl_ulong);
-        case CL_DEVICE_IMAGE2D_MAX_WIDTH: DEV_GET_INT_INF(size_t);
-        case CL_DEVICE_IMAGE2D_MAX_HEIGHT: DEV_GET_INT_INF(size_t);
-        case CL_DEVICE_IMAGE3D_MAX_WIDTH: DEV_GET_INT_INF(size_t);
-        case CL_DEVICE_IMAGE3D_MAX_HEIGHT: DEV_GET_INT_INF(size_t);
-        case CL_DEVICE_IMAGE3D_MAX_DEPTH: DEV_GET_INT_INF(size_t);
-        case CL_DEVICE_IMAGE_SUPPORT: DEV_GET_INT_INF(cl_bool);
-        case CL_DEVICE_MAX_PARAMETER_SIZE: DEV_GET_INT_INF(size_t);
-        case CL_DEVICE_MAX_SAMPLERS: DEV_GET_INT_INF(cl_uint);
-        case CL_DEVICE_MEM_BASE_ADDR_ALIGN: DEV_GET_INT_INF(cl_uint);
-        case CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE: DEV_GET_INT_INF(cl_uint);
-        case CL_DEVICE_SINGLE_FP_CONFIG: DEV_GET_INT_INF(cl_device_fp_config);
+          case CL_DEVICE_MAX_WORK_ITEM_SIZES:
+            {
+              std::vector<size_t> result;
+              PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result);
+              PYOPENCL_GET_ARRAY_INFO(size_t, result);
+            }
+
+          case CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE: DEV_GET_INT_INF(cl_uint);
+
+          case CL_DEVICE_MAX_CLOCK_FREQUENCY: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_ADDRESS_BITS: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_MAX_READ_IMAGE_ARGS: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_MAX_WRITE_IMAGE_ARGS: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_MAX_MEM_ALLOC_SIZE: DEV_GET_INT_INF(cl_ulong);
+          case CL_DEVICE_IMAGE2D_MAX_WIDTH: DEV_GET_INT_INF(size_t);
+          case CL_DEVICE_IMAGE2D_MAX_HEIGHT: DEV_GET_INT_INF(size_t);
+          case CL_DEVICE_IMAGE3D_MAX_WIDTH: DEV_GET_INT_INF(size_t);
+          case CL_DEVICE_IMAGE3D_MAX_HEIGHT: DEV_GET_INT_INF(size_t);
+          case CL_DEVICE_IMAGE3D_MAX_DEPTH: DEV_GET_INT_INF(size_t);
+          case CL_DEVICE_IMAGE_SUPPORT: DEV_GET_INT_INF(cl_bool);
+          case CL_DEVICE_MAX_PARAMETER_SIZE: DEV_GET_INT_INF(size_t);
+          case CL_DEVICE_MAX_SAMPLERS: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_MEM_BASE_ADDR_ALIGN: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_SINGLE_FP_CONFIG: DEV_GET_INT_INF(cl_device_fp_config);
 #ifdef CL_DEVICE_DOUBLE_FP_CONFIG
-        case CL_DEVICE_DOUBLE_FP_CONFIG: DEV_GET_INT_INF(cl_device_fp_config);
+          case CL_DEVICE_DOUBLE_FP_CONFIG: DEV_GET_INT_INF(cl_device_fp_config);
 #endif
 #ifdef CL_DEVICE_HALF_FP_CONFIG
-        case CL_DEVICE_HALF_FP_CONFIG: DEV_GET_INT_INF(cl_device_fp_config);
+          case CL_DEVICE_HALF_FP_CONFIG: DEV_GET_INT_INF(cl_device_fp_config);
 #endif
 
-        case CL_DEVICE_GLOBAL_MEM_CACHE_TYPE: DEV_GET_INT_INF(cl_device_mem_cache_type);
-        case CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE: DEV_GET_INT_INF(cl_uint);
-        case CL_DEVICE_GLOBAL_MEM_CACHE_SIZE: DEV_GET_INT_INF(cl_ulong);
-        case CL_DEVICE_GLOBAL_MEM_SIZE: DEV_GET_INT_INF(cl_ulong);
-
-        case CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE: DEV_GET_INT_INF(cl_ulong);
-        case CL_DEVICE_MAX_CONSTANT_ARGS: DEV_GET_INT_INF(cl_uint);
-        case CL_DEVICE_LOCAL_MEM_TYPE: DEV_GET_INT_INF(cl_device_local_mem_type);
-        case CL_DEVICE_LOCAL_MEM_SIZE: DEV_GET_INT_INF(cl_ulong);
-        case CL_DEVICE_ERROR_CORRECTION_SUPPORT: DEV_GET_INT_INF(cl_bool);
-        case CL_DEVICE_PROFILING_TIMER_RESOLUTION: DEV_GET_INT_INF(size_t);
-        case CL_DEVICE_ENDIAN_LITTLE: DEV_GET_INT_INF(cl_bool);
-        case CL_DEVICE_AVAILABLE: DEV_GET_INT_INF(cl_bool);
-        case CL_DEVICE_COMPILER_AVAILABLE: DEV_GET_INT_INF(cl_bool);
-        case CL_DEVICE_EXECUTION_CAPABILITIES: DEV_GET_INT_INF(cl_device_exec_capabilities);
-        case CL_DEVICE_QUEUE_PROPERTIES: DEV_GET_INT_INF(cl_command_queue_properties);
-
-        case CL_DEVICE_NAME:
-        case CL_DEVICE_VENDOR:
-        case CL_DRIVER_VERSION:
-        case CL_DEVICE_PROFILE:
-        case CL_DEVICE_VERSION:
-        case CL_DEVICE_EXTENSIONS:
-          PYOPENCL_GET_STR_INFO(Device, m_device, param_name);
-
-        case CL_DEVICE_PLATFORM:
-          PYOPENCL_GET_OPAQUE_INFO(Device, m_device, param_name, cl_platform_id, platform, PLATFORM);
+          case CL_DEVICE_GLOBAL_MEM_CACHE_TYPE: DEV_GET_INT_INF(cl_device_mem_cache_type);
+          case CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_GLOBAL_MEM_CACHE_SIZE: DEV_GET_INT_INF(cl_ulong);
+          case CL_DEVICE_GLOBAL_MEM_SIZE: DEV_GET_INT_INF(cl_ulong);
+
+          case CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE: DEV_GET_INT_INF(cl_ulong);
+          case CL_DEVICE_MAX_CONSTANT_ARGS: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_LOCAL_MEM_TYPE: DEV_GET_INT_INF(cl_device_local_mem_type);
+          case CL_DEVICE_LOCAL_MEM_SIZE: DEV_GET_INT_INF(cl_ulong);
+          case CL_DEVICE_ERROR_CORRECTION_SUPPORT: DEV_GET_INT_INF(cl_bool);
+          case CL_DEVICE_PROFILING_TIMER_RESOLUTION: DEV_GET_INT_INF(size_t);
+          case CL_DEVICE_ENDIAN_LITTLE: DEV_GET_INT_INF(cl_bool);
+          case CL_DEVICE_AVAILABLE: DEV_GET_INT_INF(cl_bool);
+          case CL_DEVICE_COMPILER_AVAILABLE: DEV_GET_INT_INF(cl_bool);
+          case CL_DEVICE_EXECUTION_CAPABILITIES: DEV_GET_INT_INF(cl_device_exec_capabilities);
+          case CL_DEVICE_QUEUE_PROPERTIES: DEV_GET_INT_INF(cl_command_queue_properties);
+
+          case CL_DEVICE_NAME:
+          case CL_DEVICE_VENDOR:
+          case CL_DRIVER_VERSION:
+          case CL_DEVICE_PROFILE:
+          case CL_DEVICE_VERSION:
+          case CL_DEVICE_EXTENSIONS:
+            PYOPENCL_GET_STR_INFO(Device, m_device, param_name);
+
+          case CL_DEVICE_PLATFORM:
+            PYOPENCL_GET_OPAQUE_INFO(Device, m_device, param_name, cl_platform_id, platform, PLATFORM);
 
 #if PYOPENCL_CL_VERSION >= 0x1010
-        case CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF: DEV_GET_INT_INF(cl_uint);
-
-        case CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR: DEV_GET_INT_INF(cl_uint);
-        case CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT: DEV_GET_INT_INF(cl_uint);
-        case CL_DEVICE_NATIVE_VECTOR_WIDTH_INT: DEV_GET_INT_INF(cl_uint);
-        case CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG: DEV_GET_INT_INF(cl_uint);
-        case CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT: DEV_GET_INT_INF(cl_uint);
-        case CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE: DEV_GET_INT_INF(cl_uint);
-        case CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF: DEV_GET_INT_INF(cl_uint);
-
-        case CL_DEVICE_HOST_UNIFIED_MEMORY: DEV_GET_INT_INF(cl_bool);
-        case CL_DEVICE_OPENCL_C_VERSION:
-          PYOPENCL_GET_STR_INFO(Device, m_device, param_name);
+          case CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF: DEV_GET_INT_INF(cl_uint);
+
+          case CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_NATIVE_VECTOR_WIDTH_INT: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF: DEV_GET_INT_INF(cl_uint);
+
+          case CL_DEVICE_HOST_UNIFIED_MEMORY: DEV_GET_INT_INF(cl_bool);
+          case CL_DEVICE_OPENCL_C_VERSION:
+            PYOPENCL_GET_STR_INFO(Device, m_device, param_name);
 #endif
 #ifdef CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV
-        case CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV:
-        case CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV:
-        case CL_DEVICE_REGISTERS_PER_BLOCK_NV:
-        case CL_DEVICE_WARP_SIZE_NV:
-          DEV_GET_INT_INF(cl_uint);
-        case CL_DEVICE_GPU_OVERLAP_NV:
-        case CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV:
-        case CL_DEVICE_INTEGRATED_MEMORY_NV:
-          DEV_GET_INT_INF(cl_bool);
+          case CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV:
+          case CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV:
+          case CL_DEVICE_REGISTERS_PER_BLOCK_NV:
+          case CL_DEVICE_WARP_SIZE_NV:
+            DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_GPU_OVERLAP_NV:
+          case CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV:
+          case CL_DEVICE_INTEGRATED_MEMORY_NV:
+            DEV_GET_INT_INF(cl_bool);
 #endif
 #if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION)
-        case CL_DEVICE_PARENT_DEVICE_EXT:
-          PYOPENCL_GET_OPAQUE_INFO(Device, m_device, param_name, cl_device_id, device, DEVICE);
-        case CL_DEVICE_PARTITION_TYPES_EXT:
-        case CL_DEVICE_AFFINITY_DOMAINS_EXT:
-        case CL_DEVICE_PARTITION_STYLE_EXT:
-          {
-            std::vector<cl_device_partition_property_ext> result;
-            PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result);
-            PYOPENCL_GET_ARRAY_INFO(cl_device_partition_property_ext, result);
-          }
-        case CL_DEVICE_REFERENCE_COUNT_EXT: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_PARENT_DEVICE_EXT:
+            PYOPENCL_GET_OPAQUE_INFO(Device, m_device, param_name, cl_device_id, device, DEVICE);
+          case CL_DEVICE_PARTITION_TYPES_EXT:
+          case CL_DEVICE_AFFINITY_DOMAINS_EXT:
+          case CL_DEVICE_PARTITION_STYLE_EXT:
+            {
+              std::vector<cl_device_partition_property_ext> result;
+              PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result);
+              PYOPENCL_GET_ARRAY_INFO(cl_device_partition_property_ext, result);
+            }
+          case CL_DEVICE_REFERENCE_COUNT_EXT: DEV_GET_INT_INF(cl_uint);
 #endif
 #if PYOPENCL_CL_VERSION >= 0x1020
-        case CL_DEVICE_LINKER_AVAILABLE: DEV_GET_INT_INF(cl_bool);
-        case CL_DEVICE_BUILT_IN_KERNELS:
-          PYOPENCL_GET_STR_INFO(Device, m_device, param_name);
-        case CL_DEVICE_IMAGE_MAX_BUFFER_SIZE: DEV_GET_INT_INF(size_t);
-        case CL_DEVICE_IMAGE_MAX_ARRAY_SIZE: DEV_GET_INT_INF(size_t);
-        case CL_DEVICE_PARENT_DEVICE:
-          PYOPENCL_GET_OPAQUE_INFO(Device, m_device, param_name, cl_device_id, device, DEVICE);
-        case CL_DEVICE_PARTITION_MAX_SUB_DEVICES: DEV_GET_INT_INF(cl_uint);
-        case CL_DEVICE_PARTITION_TYPE:
-        case CL_DEVICE_PARTITION_PROPERTIES:
-          {
-            std::vector<cl_device_partition_property> result;
-            PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result);
-            PYOPENCL_GET_ARRAY_INFO(cl_device_partition_property, result);
-          }
-        case CL_DEVICE_PARTITION_AFFINITY_DOMAIN:
-          {
-            std::vector<cl_device_affinity_domain> result;
-            PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result);
-            PYOPENCL_GET_ARRAY_INFO(cl_device_affinity_domain, result);
-          }
-        case CL_DEVICE_REFERENCE_COUNT: DEV_GET_INT_INF(cl_uint);
-        case CL_DEVICE_PREFERRED_INTEROP_USER_SYNC: DEV_GET_INT_INF(cl_bool);
-        case CL_DEVICE_PRINTF_BUFFER_SIZE: DEV_GET_INT_INF(cl_bool);
+          case CL_DEVICE_LINKER_AVAILABLE: DEV_GET_INT_INF(cl_bool);
+          case CL_DEVICE_BUILT_IN_KERNELS:
+            PYOPENCL_GET_STR_INFO(Device, m_device, param_name);
+          case CL_DEVICE_IMAGE_MAX_BUFFER_SIZE: DEV_GET_INT_INF(size_t);
+          case CL_DEVICE_IMAGE_MAX_ARRAY_SIZE: DEV_GET_INT_INF(size_t);
+          case CL_DEVICE_PARENT_DEVICE:
+            PYOPENCL_GET_OPAQUE_INFO(Device, m_device, param_name, cl_device_id, device, DEVICE);
+          case CL_DEVICE_PARTITION_MAX_SUB_DEVICES: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_PARTITION_TYPE:
+          case CL_DEVICE_PARTITION_PROPERTIES:
+            {
+              std::vector<cl_device_partition_property> result;
+              PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result);
+              PYOPENCL_GET_ARRAY_INFO(cl_device_partition_property, result);
+            }
+          case CL_DEVICE_PARTITION_AFFINITY_DOMAIN:
+            {
+              std::vector<cl_device_affinity_domain> result;
+              PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result);
+              PYOPENCL_GET_ARRAY_INFO(cl_device_affinity_domain, result);
+            }
+          case CL_DEVICE_REFERENCE_COUNT: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_PREFERRED_INTEROP_USER_SYNC: DEV_GET_INT_INF(cl_bool);
+          case CL_DEVICE_PRINTF_BUFFER_SIZE: DEV_GET_INT_INF(cl_bool);
 #endif
           // {{{ AMD dev attrs
           //
           // types of AMD dev attrs divined from
           // https://www.khronos.org/registry/cl/api/1.2/cl.hpp
 #ifdef CL_DEVICE_PROFILING_TIMER_OFFSET_AMD
-        case CL_DEVICE_PROFILING_TIMER_OFFSET_AMD: DEV_GET_INT_INF(cl_ulong);
+          case CL_DEVICE_PROFILING_TIMER_OFFSET_AMD: DEV_GET_INT_INF(cl_ulong);
 #endif
           /* FIXME
              #ifdef CL_DEVICE_TOPOLOGY_AMD
@@ -683,55 +717,56 @@ namespace pyopencl
              #endif
           */
 #ifdef CL_DEVICE_BOARD_NAME_AMD
-        case CL_DEVICE_BOARD_NAME_AMD: ;
-          PYOPENCL_GET_STR_INFO(Device, m_device, param_name);
+          case CL_DEVICE_BOARD_NAME_AMD: ;
+            PYOPENCL_GET_STR_INFO(Device, m_device, param_name);
 #endif
 #ifdef CL_DEVICE_GLOBAL_FREE_MEMORY_AMD
-        case CL_DEVICE_GLOBAL_FREE_MEMORY_AMD:
-          {
-            std::vector<size_t> result;
-            PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result);
-            PYOPENCL_GET_ARRAY_INFO(size_t, result);
-          }
+          case CL_DEVICE_GLOBAL_FREE_MEMORY_AMD:
+            {
+              std::vector<size_t> result;
+              PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result);
+              PYOPENCL_GET_ARRAY_INFO(size_t, result);
+            }
 #endif
 #ifdef CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD
-        case CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD: DEV_GET_INT_INF(cl_uint);
 #endif
 #ifdef CL_DEVICE_SIMD_WIDTH_AMD
-        case CL_DEVICE_SIMD_WIDTH_AMD: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_SIMD_WIDTH_AMD: DEV_GET_INT_INF(cl_uint);
 #endif
 #ifdef CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD
-        case CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD: DEV_GET_INT_INF(cl_uint);
 #endif
 #ifdef CL_DEVICE_WAVEFRONT_WIDTH_AMD
-        case CL_DEVICE_WAVEFRONT_WIDTH_AMD: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_WAVEFRONT_WIDTH_AMD: DEV_GET_INT_INF(cl_uint);
 #endif
 #ifdef CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD
-        case CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD: DEV_GET_INT_INF(cl_uint);
 #endif
 #ifdef CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD
-        case CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD: DEV_GET_INT_INF(cl_uint);
 #endif
 #ifdef CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD
-        case CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD: DEV_GET_INT_INF(cl_uint);
 #endif
 #ifdef CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD
-        case CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD: DEV_GET_INT_INF(cl_uint);
 #endif
 #ifdef CL_DEVICE_LOCAL_MEM_BANKS_AMD
-        case CL_DEVICE_LOCAL_MEM_BANKS_AMD: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_LOCAL_MEM_BANKS_AMD: DEV_GET_INT_INF(cl_uint);
 #endif
           // }}}
 
 #ifdef CL_DEVICE_MAX_ATOMIC_COUNTERS_EXT
-        case CL_DEVICE_MAX_ATOMIC_COUNTERS_EXT: DEV_GET_INT_INF(cl_uint);
+          case CL_DEVICE_MAX_ATOMIC_COUNTERS_EXT: DEV_GET_INT_INF(cl_uint);
 #endif
 
-        default:
-          throw error("Device.get_info", CL_INVALID_VALUE);
-        }
-    }
+          default:
+            throw error("Device.get_info", CL_INVALID_VALUE);
+          }
+      }
 
+    // TODO: sub-devices
     // #if PYOPENCL_CL_VERSION >= 0x1020
     //       py::list create_sub_devices(py::object py_properties)
     //       {
@@ -806,57 +841,57 @@ namespace pyopencl
   // }}}
 
 
-
   // {{{ context
-  class context : public _common // : public boost::noncopyable
+
+  class context : public noncopyable
   {
-  private:
-    cl_context m_context;
+    private:
+      cl_context m_context;
 
-  public:
-    context(cl_context ctx, bool retain)
-      : m_context(ctx)
-    {
-      if (retain)
-        PYOPENCL_CALL_GUARDED(clRetainContext, (ctx));
-    }
+    public:
+      context(cl_context ctx, bool retain)
+        : m_context(ctx)
+      {
+        if (retain)
+          PYOPENCL_CALL_GUARDED(clRetainContext, (ctx));
+      }
 
 
-    ~context()
-    {
-      PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseContext,
-                                    (m_context));
-    }
+      ~context()
+      {
+        PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseContext, (m_context));
+      }
 
-    cl_context data() const
-    {
-      return m_context;
-    }
+      cl_context data() const
+      {
+        return m_context;
+      }
 
-    PYOPENCL_EQUALITY_TESTS(context);
+      PYOPENCL_EQUALITY_TESTS(context);
 
-    generic_info get_info(cl_context_info param_name) const
-    {
-      switch (param_name)
+      generic_info get_info(cl_context_info param_name) const
+      {
+        switch (param_name)
         {
-        case CL_CONTEXT_REFERENCE_COUNT:
-          PYOPENCL_GET_INTEGRAL_INFO(Context, m_context, param_name, cl_uint);
+          case CL_CONTEXT_REFERENCE_COUNT:
+            PYOPENCL_GET_INTEGRAL_INFO(Context, m_context, param_name, cl_uint);
 
-        case CL_CONTEXT_DEVICES:
-          {
-            std::vector<cl_device_id> result;
-            PYOPENCL_GET_VEC_INFO(Context, m_context, param_name, result);
-            PYOPENCL_GET_OPAQUE_ARRAY_INFO(cl_device_id, device, DEVICE, result);
+          case CL_CONTEXT_DEVICES:
+            {
+              std::vector<cl_device_id> result;
+              PYOPENCL_GET_VEC_INFO(Context, m_context, param_name, result);
+              PYOPENCL_GET_OPAQUE_ARRAY_INFO(cl_device_id, device, DEVICE, result);
 
-          }
+            }
 
-        case CL_CONTEXT_PROPERTIES:
-          {
+          case CL_CONTEXT_PROPERTIES:
+            {
+              std::vector<cl_context_properties> result;
+              PYOPENCL_GET_VEC_INFO(Context, m_context, param_name, result);
+
+              std::vector<generic_info> py_result;
 
-            std::vector<cl_context_properties> result;
-            PYOPENCL_GET_VEC_INFO(Context, m_context, param_name, result);
-            std::vector<generic_info> py_result;
-            for (size_t i = 0; i < result.size(); i+=2)
+              for (size_t i = 0; i < result.size(); i+=2)
               {
                 cl_context_properties key = result[i];
                 if(key == 0)
@@ -865,7 +900,7 @@ namespace pyopencl
                 info.dontfree = 0;
                 info.opaque_class = CLASS_NONE;
                 switch (key)
-                  {
+                {
                   case CL_CONTEXT_PLATFORM:
                     {
                       info.opaque_class = CLASS_PLATFORM;
@@ -893,90 +928,92 @@ namespace pyopencl
 #endif
                   default:
                     throw error("Context.get_info", CL_INVALID_VALUE,
-                                "unknown context_property key encountered");
-                  }
+                        "unknown context_property key encountered");
+                }
 
                 py_result.push_back(info);
               }
-            PYOPENCL_GET_ARRAY_INFO(generic_info, py_result);
-          }
+              PYOPENCL_GET_ARRAY_INFO(generic_info, py_result);
+            }
 
 #if PYOPENCL_CL_VERSION >= 0x1010
-        case CL_CONTEXT_NUM_DEVICES:
-          PYOPENCL_GET_INTEGRAL_INFO(Context, m_context, param_name, cl_uint);
+          case CL_CONTEXT_NUM_DEVICES:
+            PYOPENCL_GET_INTEGRAL_INFO(Context, m_context, param_name, cl_uint);
 #endif
 
-        default:
-          throw error("Context.get_info", CL_INVALID_VALUE);
+          default:
+            throw error("Context.get_info", CL_INVALID_VALUE);
         }
-    }
-
-    // }}}
+      }
 
   };
 
+  // }}}
+
+
   // {{{ command_queue
-  class command_queue : public _common
+
+  class command_queue : public noncopyable
   {
-  private:
-    cl_command_queue m_queue;
+    private:
+      cl_command_queue m_queue;
 
-  public:
-    command_queue(cl_command_queue q, bool retain)
-      : m_queue(q)
-    {
-      if (retain)
-        PYOPENCL_CALL_GUARDED(clRetainCommandQueue, (q));
-    }
+    public:
+      command_queue(cl_command_queue q, bool retain)
+        : m_queue(q)
+      {
+        if (retain)
+          PYOPENCL_CALL_GUARDED(clRetainCommandQueue, (q));
+      }
 
-    command_queue(command_queue const &src)
-      : m_queue(src.m_queue)
-    {
-      PYOPENCL_CALL_GUARDED(clRetainCommandQueue, (m_queue));
-    }
+      command_queue(command_queue const &src)
+        : m_queue(src.m_queue)
+      {
+        PYOPENCL_CALL_GUARDED(clRetainCommandQueue, (m_queue));
+      }
 
-    command_queue(
-                  const context &ctx,
-                  const device *py_dev=0,
-                  cl_command_queue_properties props=0)
-    {
-      cl_device_id dev;
-      if (py_dev)
-        dev = py_dev->data();
-      else
-        {
-          std::vector<cl_device_id> devs;
-          PYOPENCL_GET_VEC_INFO(Context, ctx.data(), CL_CONTEXT_DEVICES, devs);
-          if (devs.size() == 0)
-            throw pyopencl::error("CommandQueue", CL_INVALID_VALUE,
-                                  "context doesn't have any devices? -- don't know which one to default to");
-          dev = devs[0];
-        }
+      command_queue(
+                    const context &ctx,
+                    const device *py_dev=0,
+                    cl_command_queue_properties props=0)
+      {
+        cl_device_id dev;
+        if (py_dev)
+          dev = py_dev->data();
+        else
+          {
+            std::vector<cl_device_id> devs;
+            PYOPENCL_GET_VEC_INFO(Context, ctx.data(), CL_CONTEXT_DEVICES, devs);
+            if (devs.size() == 0)
+              throw pyopencl::error("CommandQueue", CL_INVALID_VALUE,
+                                    "context doesn't have any devices? -- don't know which one to default to");
+            dev = devs[0];
+          }
 
-      cl_int status_code;
-      PYOPENCL_PRINT_CALL_TRACE("clCreateCommandQueue");
-      m_queue = clCreateCommandQueue(
-                                     ctx.data(), dev, props, &status_code);
+        cl_int status_code;
+        PYOPENCL_PRINT_CALL_TRACE("clCreateCommandQueue");
+        m_queue = clCreateCommandQueue(
+                                       ctx.data(), dev, props, &status_code);
 
-      if (status_code != CL_SUCCESS) {
-        throw pyopencl::error("CommandQueue", status_code);
+        if (status_code != CL_SUCCESS) {
+          throw pyopencl::error("CommandQueue", status_code);
+        }
       }
-    }
 
-    ~command_queue()
-    {
-      PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseCommandQueue,
-                                    (m_queue));
-    }
+      ~command_queue()
+      {
+        PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseCommandQueue,
+                                      (m_queue));
+      }
 
-    const cl_command_queue data() const
-    { return m_queue; }
+      const cl_command_queue data() const
+      { return m_queue; }
 
-    PYOPENCL_EQUALITY_TESTS(command_queue);
+      PYOPENCL_EQUALITY_TESTS(command_queue);
 
-    generic_info get_info(cl_command_queue_info param_name) const
-    {
-      switch (param_name)
+      generic_info get_info(cl_command_queue_info param_name) const
+      {
+        switch (param_name)
         {
         case CL_QUEUE_CONTEXT:
           PYOPENCL_GET_OPAQUE_INFO(CommandQueue, m_queue, param_name,
@@ -993,21 +1030,21 @@ namespace pyopencl
         default:
           throw error("CommandQueue.get_info", CL_INVALID_VALUE);
         }
-    }
+      }
 
-    std::auto_ptr<context> get_context() const
-    {
-      cl_context param_value;
-      PYOPENCL_CALL_GUARDED(clGetCommandQueueInfo,
-                            (m_queue, CL_QUEUE_CONTEXT, sizeof(param_value), &param_value, 0));
-      return std::auto_ptr<context>(
-                                    new context(param_value, /*retain*/ true));
-    }
+      std::auto_ptr<context> get_context() const
+      {
+        cl_context param_value;
+        PYOPENCL_CALL_GUARDED(clGetCommandQueueInfo,
+            (m_queue, CL_QUEUE_CONTEXT, sizeof(param_value), &param_value, 0));
+        return std::auto_ptr<context>(
+            new context(param_value, /*retain*/ true));
+      }
 
 #if PYOPENCL_CL_VERSION < 0x1010
     cl_command_queue_properties set_property(
-                                             cl_command_queue_properties prop,
-                                             bool enable)
+        cl_command_queue_properties prop,
+        bool enable)
     {
       cl_command_queue_properties old_prop;
       PYOPENCL_CALL_GUARDED(clSetCommandQueueProperty,
@@ -1018,6 +1055,7 @@ namespace pyopencl
 
     void flush()
     { PYOPENCL_CALL_GUARDED(clFlush, (m_queue)); }
+
     void finish()
     {
       // TODO
@@ -1028,81 +1066,82 @@ namespace pyopencl
   // }}}
 
 
-  // {{{ event/synchronization
-  class event : public _common // : boost::noncopyable
+  // {{{ event
+
+  class event : public noncopyable
   {
-  private:
-    cl_event m_event;
+    private:
+      cl_event m_event;
 
-  public:
-    event(cl_event event, bool retain)
-      : m_event(event)
-    {
-      if (retain)
-        PYOPENCL_CALL_GUARDED(clRetainEvent, (event));
-    }
+    public:
+      event(cl_event event, bool retain)
+        : m_event(event)
+      {
+        if (retain)
+          PYOPENCL_CALL_GUARDED(clRetainEvent, (event));
+      }
 
-    event(event const &src)
-      : m_event(src.m_event)
-    { PYOPENCL_CALL_GUARDED(clRetainEvent, (m_event)); }
+      event(event const &src)
+        : m_event(src.m_event)
+      { PYOPENCL_CALL_GUARDED(clRetainEvent, (m_event)); }
 
-    virtual ~event()
-    {
-      PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseEvent,
-                                    (m_event));
-    }
+      virtual ~event()
+      {
+        PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseEvent,
+            (m_event));
+      }
 
-    const cl_event data() const
-    { return m_event; }
+      const cl_event data() const
+      { return m_event; }
 
-    PYOPENCL_EQUALITY_TESTS(event);
+      PYOPENCL_EQUALITY_TESTS(event);
 
-    generic_info get_info(cl_event_info param_name) const
-    {
-      switch (param_name)
+      generic_info get_info(cl_event_info param_name) const
+      {
+        switch (param_name)
         {
-        case CL_EVENT_COMMAND_QUEUE:
-          PYOPENCL_GET_OPAQUE_INFO(Event, m_event, param_name,
-                                   cl_command_queue, command_queue, COMMAND_QUEUE);
-        case CL_EVENT_COMMAND_TYPE:
-          PYOPENCL_GET_INTEGRAL_INFO(Event, m_event, param_name,
-                                     cl_command_type);
-        case CL_EVENT_COMMAND_EXECUTION_STATUS:
-          PYOPENCL_GET_INTEGRAL_INFO(Event, m_event, param_name,
-                                     cl_int);
-        case CL_EVENT_REFERENCE_COUNT:
-          PYOPENCL_GET_INTEGRAL_INFO(Event, m_event, param_name,
-                                     cl_uint);
+          case CL_EVENT_COMMAND_QUEUE:
+            PYOPENCL_GET_OPAQUE_INFO(Event, m_event, param_name,
+                cl_command_queue, command_queue, COMMAND_QUEUE);
+          case CL_EVENT_COMMAND_TYPE:
+            PYOPENCL_GET_INTEGRAL_INFO(Event, m_event, param_name,
+                cl_command_type);
+          case CL_EVENT_COMMAND_EXECUTION_STATUS:
+            PYOPENCL_GET_INTEGRAL_INFO(Event, m_event, param_name,
+                cl_int);
+          case CL_EVENT_REFERENCE_COUNT:
+            PYOPENCL_GET_INTEGRAL_INFO(Event, m_event, param_name,
+                cl_uint);
 #if PYOPENCL_CL_VERSION >= 0x1010
-        case CL_EVENT_CONTEXT:
-          PYOPENCL_GET_OPAQUE_INFO(Event, m_event, param_name,
-                                   cl_context, context, CONTEXT);
+          case CL_EVENT_CONTEXT:
+            PYOPENCL_GET_OPAQUE_INFO(Event, m_event, param_name,
+                cl_context, context, CONTEXT);
 #endif
 
-        default:
-          throw error("Event.get_info", CL_INVALID_VALUE);
+          default:
+            throw error("Event.get_info", CL_INVALID_VALUE);
         }
-    }
+      }
 
-    generic_info get_profiling_info(cl_profiling_info param_name) const
-    {
-      switch (param_name)
+      generic_info get_profiling_info(cl_profiling_info param_name) const
+      {
+        switch (param_name)
         {
-        case CL_PROFILING_COMMAND_QUEUED:
-        case CL_PROFILING_COMMAND_SUBMIT:
-        case CL_PROFILING_COMMAND_START:
-        case CL_PROFILING_COMMAND_END:
-          PYOPENCL_GET_INTEGRAL_INFO(EventProfiling, m_event, param_name,
-                                     cl_ulong);
-        default:
-          throw error("Event.get_profiling_info", CL_INVALID_VALUE);
+          case CL_PROFILING_COMMAND_QUEUED:
+          case CL_PROFILING_COMMAND_SUBMIT:
+          case CL_PROFILING_COMMAND_START:
+          case CL_PROFILING_COMMAND_END:
+            PYOPENCL_GET_INTEGRAL_INFO(EventProfiling, m_event, param_name,
+                cl_ulong);
+          default:
+            throw error("Event.get_profiling_info", CL_INVALID_VALUE);
         }
-    }
+      }
 
-    virtual void wait()
-    {
-      PYOPENCL_CALL_GUARDED_THREADED(clWaitForEvents, (1, &m_event));
-    }
+      virtual void wait()
+      {
+        PYOPENCL_CALL_GUARDED_THREADED(clWaitForEvents, (1, &m_event));
+      }
   };
 
   // }}}
@@ -1112,121 +1151,121 @@ namespace pyopencl
 
   //py::object create_mem_object_wrapper(cl_mem mem);
 
-  class memory_object_holder : public _common
+  class memory_object_holder : public noncopyable
   {
-  public:
-    virtual const cl_mem data() const = 0;
+    public:
+      virtual const cl_mem data() const = 0;
 
-    PYOPENCL_EQUALITY_TESTS(memory_object_holder);
+      PYOPENCL_EQUALITY_TESTS(memory_object_holder);
 
-    size_t size() const
-    {
-      size_t param_value;
-      PYOPENCL_CALL_GUARDED(clGetMemObjectInfo,
-                            (data(), CL_MEM_SIZE, sizeof(param_value), &param_value, 0));
-      return param_value;
-    }
+      size_t size() const
+      {
+        size_t param_value;
+        PYOPENCL_CALL_GUARDED(clGetMemObjectInfo,
+            (data(), CL_MEM_SIZE, sizeof(param_value), &param_value, 0));
+        return param_value;
+      }
 
-    generic_info get_info(cl_mem_info param_name) {
-      switch (param_name){
-      case CL_MEM_TYPE:
-        PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name,
-                                   cl_mem_object_type);
-      case CL_MEM_FLAGS:
-        PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name,
-                                   cl_mem_flags);
-      case CL_MEM_SIZE:
-        PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name,
-                                   size_t);
-      case CL_MEM_HOST_PTR:
-        throw pyopencl::error("MemoryObject.get_info", CL_INVALID_VALUE,
-                              "Use MemoryObject.get_host_array to get host pointer.");
-      case CL_MEM_MAP_COUNT:
-        PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name,
-                                   cl_uint);
-      case CL_MEM_REFERENCE_COUNT:
-        PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name,
-                                   cl_uint);
-      case CL_MEM_CONTEXT:
-        PYOPENCL_GET_OPAQUE_INFO(MemObject, data(), param_name,
-                                 cl_context, context, CONTEXT);
+      generic_info get_info(cl_mem_info param_name) {
+        switch (param_name){
+          case CL_MEM_TYPE:
+            PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name,
+                cl_mem_object_type);
+          case CL_MEM_FLAGS:
+            PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name,
+                cl_mem_flags);
+          case CL_MEM_SIZE:
+            PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name,
+                size_t);
+          case CL_MEM_HOST_PTR:
+            throw pyopencl::error("MemoryObject.get_info", CL_INVALID_VALUE,
+                "Use MemoryObject.get_host_array to get host pointer.");
+          case CL_MEM_MAP_COUNT:
+            PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name,
+                cl_uint);
+          case CL_MEM_REFERENCE_COUNT:
+            PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name,
+                cl_uint);
+          case CL_MEM_CONTEXT:
+            PYOPENCL_GET_OPAQUE_INFO(MemObject, data(), param_name,
+                cl_context, context, CONTEXT);
 
 #if PYOPENCL_CL_VERSION >= 0x1010
-        //       case CL_MEM_ASSOCIATED_MEMOBJECT:
-        //      {
-        //        cl_mem param_value;
-        //        PYOPENCL_CALL_GUARDED(clGetMemObjectInfo, (data(), param_name, sizeof(param_value), &param_value, 0));
-        //        if (param_value == 0)
-        //          {
-        //            // no associated memory object? no problem.
-        //            return py::object();
-        //          }
-
-        //        return create_mem_object_wrapper(param_value);
-        //      }
-      case CL_MEM_OFFSET:
-        PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name,
-                                   size_t);
+            // TODO
+            //       case CL_MEM_ASSOCIATED_MEMOBJECT:
+            //      {
+            //        cl_mem param_value;
+            //        PYOPENCL_CALL_GUARDED(clGetMemObjectInfo, (data(), param_name, sizeof(param_value), &param_value, 0));
+            //        if (param_value == 0)
+            //          {
+            //            // no associated memory object? no problem.
+            //            return py::object();
+            //          }
+
+            //        return create_mem_object_wrapper(param_value);
+            //      }
+          case CL_MEM_OFFSET:
+            PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name,
+                size_t);
 #endif
 
-      default:
-        throw error("MemoryObjectHolder.get_info", CL_INVALID_VALUE);
+          default:
+            throw error("MemoryObjectHolder.get_info", CL_INVALID_VALUE);
+        }
       }
-    }
   };
 
 
-  class memory_object : /*boost::noncopyable, */ public memory_object_holder
+  class memory_object : public memory_object_holder
   {
-  private:
-    bool m_valid;
-    cl_mem m_mem;
-    void *m_hostbuf;
-
-  public:
-    memory_object(cl_mem mem, bool retain, void *hostbuf=0)
-      : m_valid(true), m_mem(mem)
-    {
-      if (retain)
-        PYOPENCL_CALL_GUARDED(clRetainMemObject, (mem));
+    private:
+      bool m_valid;
+      cl_mem m_mem;
+      void *m_hostbuf;
 
-      if (hostbuf)
-        m_hostbuf = hostbuf;
-    }
+    public:
+      memory_object(cl_mem mem, bool retain, void *hostbuf=0)
+        : m_valid(true), m_mem(mem)
+      {
+        if (retain)
+          PYOPENCL_CALL_GUARDED(clRetainMemObject, (mem));
 
-    memory_object(memory_object const &src)
-      : m_valid(true), m_mem(src.m_mem), m_hostbuf(src.m_hostbuf)
-    {
-      PYOPENCL_CALL_GUARDED(clRetainMemObject, (m_mem));
-    }
+        if (hostbuf)
+          m_hostbuf = hostbuf;
+      }
 
-    memory_object(memory_object_holder const &src)
-      : m_valid(true), m_mem(src.data())
-    {
-      PYOPENCL_CALL_GUARDED(clRetainMemObject, (m_mem));
-    }
+      memory_object(memory_object const &src)
+        : m_valid(true), m_mem(src.m_mem), m_hostbuf(src.m_hostbuf)
+      {
+        PYOPENCL_CALL_GUARDED(clRetainMemObject, (m_mem));
+      }
 
-    void release()
-    {
-      if (!m_valid)
-        throw error("MemoryObject.free", CL_INVALID_VALUE,
-                    "trying to double-unref mem object");
-      PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseMemObject, (m_mem));
-      m_valid = false;
-    }
+      memory_object(memory_object_holder const &src)
+        : m_valid(true), m_mem(src.data())
+      {
+        PYOPENCL_CALL_GUARDED(clRetainMemObject, (m_mem));
+      }
 
-    virtual ~memory_object()
-    {
-      if (m_valid)
-        release();
-    }
+      void release()
+      {
+        if (!m_valid)
+          throw error("MemoryObject.free", CL_INVALID_VALUE,
+              "trying to double-unref mem object");
+        PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseMemObject, (m_mem));
+        m_valid = false;
+      }
 
-    void *hostbuf()
-    { return m_hostbuf; }
+      virtual ~memory_object()
+      {
+        if (m_valid)
+          release();
+      }
 
-    const cl_mem data() const
-    { return m_mem; }
+      void *hostbuf()
+      { return m_hostbuf; }
 
+      const cl_mem data() const
+      { return m_mem; }
   };
 
   // #if PYOPENCL_CL_VERSION >= 0x1020
@@ -1304,52 +1343,53 @@ namespace pyopencl
 
   class image : public memory_object
   {
-  public:
-    image(cl_mem mem, bool retain, void *hostbuf=0)
-      : memory_object(mem, retain, hostbuf)
-    { }
+    public:
+      image(cl_mem mem, bool retain, void *hostbuf=0)
+        : memory_object(mem, retain, hostbuf)
+      { }
 
-    generic_info get_image_info(cl_image_info param_name) const
-    {
-      switch (param_name)
+      generic_info get_image_info(cl_image_info param_name) const
+      {
+        switch (param_name)
         {
-        case CL_IMAGE_FORMAT:
-          PYOPENCL_GET_INTEGRAL_INFO(Image, data(), param_name,
-                                     cl_image_format);
-        case CL_IMAGE_ELEMENT_SIZE:
-        case CL_IMAGE_ROW_PITCH:
-        case CL_IMAGE_SLICE_PITCH:
-        case CL_IMAGE_WIDTH:
-        case CL_IMAGE_HEIGHT:
-        case CL_IMAGE_DEPTH:
+          case CL_IMAGE_FORMAT:
+            PYOPENCL_GET_INTEGRAL_INFO(Image, data(), param_name,
+                cl_image_format);
+          case CL_IMAGE_ELEMENT_SIZE:
+          case CL_IMAGE_ROW_PITCH:
+          case CL_IMAGE_SLICE_PITCH:
+          case CL_IMAGE_WIDTH:
+          case CL_IMAGE_HEIGHT:
+          case CL_IMAGE_DEPTH:
 #if PYOPENCL_CL_VERSION >= 0x1020
-        case CL_IMAGE_ARRAY_SIZE:
+          case CL_IMAGE_ARRAY_SIZE:
 #endif
-          PYOPENCL_GET_INTEGRAL_INFO(Image, data(), param_name, size_t);
+            PYOPENCL_GET_INTEGRAL_INFO(Image, data(), param_name, size_t);
 
 #if PYOPENCL_CL_VERSION >= 0x1020
-          //    case CL_IMAGE_BUFFER:
-          //      {
-          //        cl_mem param_value;
-          //        PYOPENCL_CALL_GUARDED(clGetImageInfo, (data(), param_name, sizeof(param_value), &param_value, 0));
-          //        if (param_value == 0)
-          //               {
-          //                 // no associated memory object? no problem.
-          //                 return py::object();
-          //               }
-
-          //        return create_mem_object_wrapper(param_value);
-          //      }
-
-        case CL_IMAGE_NUM_MIP_LEVELS:
-        case CL_IMAGE_NUM_SAMPLES:
-          PYOPENCL_GET_INTEGRAL_INFO(Image, data(), param_name, cl_uint);
+            // TODO:
+            //    case CL_IMAGE_BUFFER:
+            //      {
+            //        cl_mem param_value;
+            //        PYOPENCL_CALL_GUARDED(clGetImageInfo, (data(), param_name, sizeof(param_value), &param_value, 0));
+            //        if (param_value == 0)
+            //               {
+            //                 // no associated memory object? no problem.
+            //                 return py::object();
+            //               }
+
+            //        return create_mem_object_wrapper(param_value);
+            //      }
+
+          case CL_IMAGE_NUM_MIP_LEVELS:
+          case CL_IMAGE_NUM_SAMPLES:
+            PYOPENCL_GET_INTEGRAL_INFO(Image, data(), param_name, cl_uint);
 #endif
 
-        default:
-          throw error("MemoryObject.get_image_info", CL_INVALID_VALUE);
+          default:
+            throw error("MemoryObject.get_image_info", CL_INVALID_VALUE);
         }
-    }
+      }
   };
 
 
@@ -1392,8 +1432,8 @@ namespace pyopencl
       retained_buf_obj = buffer;
 
     PYOPENCL_PRINT_CALL_TRACE("clCreateImage2D");
-    //
-    //PYOPENCL_RETRY_IF_MEM_ERROR(
+
+    // PYOPENCL_RETRY_IF_MEM_ERROR(
     {
       mem = clCreateImage2D(ctx.data(), flags, &fmt,
                             width, height, pitch, buffer, &status_code);
@@ -1403,14 +1443,14 @@ namespace pyopencl
     //);
 
     try
-      {
-        return new image(mem, false, retained_buf_obj);
-      }
+    {
+      return new image(mem, false, retained_buf_obj);
+    }
     catch (...)
-      {
-        PYOPENCL_CALL_GUARDED(clReleaseMemObject, (mem));
-        throw;
-      }
+    {
+      PYOPENCL_CALL_GUARDED(clReleaseMemObject, (mem));
+      throw;
+    }
   }
 
   inline
@@ -1829,6 +1869,7 @@ namespace pyopencl
 
 
 
+  // TODO:
   // inline
   // py::tuple get_gl_object_info(memory_object_holder const &mem)
   // {
@@ -1955,7 +1996,6 @@ namespace pyopencl
   // }}}
 
 
-
   // {{{ buffer
 
   inline cl_mem create_buffer(
@@ -2110,6 +2150,7 @@ namespace pyopencl
   // }}}
   // }}}
 
+
   // {{{ sampler
   class sampler // : boost::noncopyable
   {
@@ -2181,187 +2222,260 @@ namespace pyopencl
 
   // {{{ program
 
-  class program : public _common //: boost::noncopyable
+  class program : public noncopyable
   {
+    private:
+      cl_program m_program;
+      program_kind_type m_program_kind;
 
-  private:
-    cl_program m_program;
-    program_kind_type m_program_kind;
-
-  public:
-    program(cl_program prog, bool retain, program_kind_type progkind=KND_UNKNOWN)
-      : m_program(prog), m_program_kind(progkind)
-    {
-      if (retain)
-        PYOPENCL_CALL_GUARDED(clRetainProgram, (prog));
-    }
+    public:
+      program(cl_program prog, bool retain, program_kind_type progkind=KND_UNKNOWN)
+        : m_program(prog), m_program_kind(progkind)
+      {
+        if (retain)
+          PYOPENCL_CALL_GUARDED(clRetainProgram, (prog));
+      }
 
-    ~program()
-    {
-      PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseProgram, (m_program));
-    }
+      ~program()
+      {
+        PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseProgram, (m_program));
+      }
 
-    cl_program data() const
-    {
-      return m_program;
-    }
+      cl_program data() const
+      {
+        return m_program;
+      }
 
-    program_kind_type kind() const
-    {
-      return m_program_kind;
-    }
+      program_kind_type kind() const
+      {
+        return m_program_kind;
+      }
 
-    PYOPENCL_EQUALITY_TESTS(program);
+      PYOPENCL_EQUALITY_TESTS(program);
 
-    std::vector<cl_device_id> get_info__devices()
-    {
-      std::vector<cl_device_id> result;
-      PYOPENCL_GET_VEC_INFO(Program, m_program, CL_PROGRAM_DEVICES, result);
-      return result;
-    }
+      std::vector<cl_device_id> get_info__devices()
+      {
+        std::vector<cl_device_id> result;
+        PYOPENCL_GET_VEC_INFO(Program, m_program, CL_PROGRAM_DEVICES, result);
+        return result;
+      }
 
-    generic_info get_info(cl_program_info param_name) const
-    {
-      switch (param_name)
+      generic_info get_info(cl_program_info param_name) const
+      {
+        switch (param_name)
         {
-        case CL_PROGRAM_REFERENCE_COUNT:
-          PYOPENCL_GET_INTEGRAL_INFO(Program, m_program, param_name,
-                                     cl_uint);
-        case CL_PROGRAM_CONTEXT:
-          PYOPENCL_GET_OPAQUE_INFO(Program, m_program, param_name,
-                                   cl_context, context, CONTEXT);
-        case CL_PROGRAM_NUM_DEVICES:
-          PYOPENCL_GET_INTEGRAL_INFO(Program, m_program, param_name,
-                                     cl_uint);
-        case CL_PROGRAM_DEVICES:
-          {
-            std::vector<cl_device_id> result;
-            PYOPENCL_GET_VEC_INFO(Program, m_program, param_name, result);
-            PYOPENCL_GET_OPAQUE_ARRAY_INFO(cl_device_id, device, DEVICE, result);
-          }
-        case CL_PROGRAM_SOURCE:
-          PYOPENCL_GET_STR_INFO(Program, m_program, param_name);
-        case CL_PROGRAM_BINARY_SIZES:
-          {
-            std::vector<size_t> result;
-            PYOPENCL_GET_VEC_INFO(Program, m_program, param_name, result);
-            PYOPENCL_GET_ARRAY_INFO(size_t, result);
-          }
-        case CL_PROGRAM_BINARIES:
-          {
-            std::vector<size_t> sizes;
-            PYOPENCL_GET_VEC_INFO(Program, m_program, CL_PROGRAM_BINARY_SIZES, sizes);
-            std::vector<char *> result_ptrs(sizes.size());
-            for (unsigned i = 0; i < sizes.size(); ++i) {
-              result_ptrs[i] = new char[sizes[i]];
+          case CL_PROGRAM_REFERENCE_COUNT:
+            PYOPENCL_GET_INTEGRAL_INFO(Program, m_program, param_name,
+                cl_uint);
+          case CL_PROGRAM_CONTEXT:
+            PYOPENCL_GET_OPAQUE_INFO(Program, m_program, param_name,
+                cl_context, context, CONTEXT);
+          case CL_PROGRAM_NUM_DEVICES:
+            PYOPENCL_GET_INTEGRAL_INFO(Program, m_program, param_name,
+                cl_uint);
+          case CL_PROGRAM_DEVICES:
+            {
+              std::vector<cl_device_id> result;
+              PYOPENCL_GET_VEC_INFO(Program, m_program, param_name, result);
+              PYOPENCL_GET_OPAQUE_ARRAY_INFO(cl_device_id, device, DEVICE, result);
             }
-            std::vector<generic_info> gis(sizes.size());
-            for(unsigned i = 0; i < sizes.size(); ++i) {
-              gis[i].opaque_class = CLASS_NONE;
-              gis[i].type =  _copy_str(std::string("char[") + tostring(sizes[i]) + "]");
-              gis[i].value = result_ptrs[i];
+          case CL_PROGRAM_SOURCE:
+            PYOPENCL_GET_STR_INFO(Program, m_program, param_name);
+          case CL_PROGRAM_BINARY_SIZES:
+            {
+              std::vector<size_t> result;
+              PYOPENCL_GET_VEC_INFO(Program, m_program, param_name, result);
+              PYOPENCL_GET_ARRAY_INFO(size_t, result);
+            }
+          case CL_PROGRAM_BINARIES:
+            {
+              std::vector<size_t> sizes;
+              PYOPENCL_GET_VEC_INFO(Program, m_program, CL_PROGRAM_BINARY_SIZES, sizes);
+              std::vector<char *> result_ptrs(sizes.size());
+              for (unsigned i = 0; i < sizes.size(); ++i) {
+                result_ptrs[i] = new char[sizes[i]];
+              }
+              std::vector<generic_info> gis(sizes.size());
+              for(unsigned i = 0; i < sizes.size(); ++i) {
+                gis[i].opaque_class = CLASS_NONE;
+                gis[i].type =  _copy_str(std::string("char[") + tostring(sizes[i]) + "]");
+                gis[i].value = result_ptrs[i];
+              }
+              PYOPENCL_CALL_GUARDED(clGetProgramInfo,
+                  (m_program, CL_PROGRAM_BINARIES, sizes.size()*sizeof(char *),
+                   &result_ptrs.front(), 0));
+              PYOPENCL_GET_ARRAY_INFO(generic_info, gis);
             }
-            PYOPENCL_CALL_GUARDED(clGetProgramInfo,
-                                  (m_program, CL_PROGRAM_BINARIES, sizes.size()*sizeof(char *),
-                                   &result_ptrs.front(), 0));
-            PYOPENCL_GET_ARRAY_INFO(generic_info, gis);
-          }
 
 #if PYOPENCL_CL_VERSION >= 0x1020
-        case CL_PROGRAM_NUM_KERNELS:
-          PYOPENCL_GET_INTEGRAL_INFO(Program, m_program, param_name,
-                                     size_t);
-        case CL_PROGRAM_KERNEL_NAMES:
-          PYOPENCL_GET_STR_INFO(Program, m_program, param_name);
+          case CL_PROGRAM_NUM_KERNELS:
+            PYOPENCL_GET_INTEGRAL_INFO(Program, m_program, param_name,
+                size_t);
+          case CL_PROGRAM_KERNEL_NAMES:
+            PYOPENCL_GET_STR_INFO(Program, m_program, param_name);
 #endif
 
-        default:
-          throw error("Program.get_info", CL_INVALID_VALUE);
+          default:
+            throw error("Program.get_info", CL_INVALID_VALUE);
         }
-    }
+      }
 
-    generic_info get_build_info(device const &dev,
-                                cl_program_build_info param_name) const
-    {
-      switch (param_name)
+      generic_info get_build_info(device const &dev,
+          cl_program_build_info param_name) const
+      {
+        switch (param_name)
         {
 #define PYOPENCL_FIRST_ARG m_program, dev.data() // hackety hack
-        case CL_PROGRAM_BUILD_STATUS:
-          PYOPENCL_GET_INTEGRAL_INFO(ProgramBuild,
-                                     PYOPENCL_FIRST_ARG, param_name,
-                                     cl_build_status);
-        case CL_PROGRAM_BUILD_OPTIONS:
-        case CL_PROGRAM_BUILD_LOG:
-          PYOPENCL_GET_STR_INFO(ProgramBuild,
-                                PYOPENCL_FIRST_ARG, param_name);
+          case CL_PROGRAM_BUILD_STATUS:
+            PYOPENCL_GET_INTEGRAL_INFO(ProgramBuild,
+                PYOPENCL_FIRST_ARG, param_name,
+                cl_build_status);
+          case CL_PROGRAM_BUILD_OPTIONS:
+          case CL_PROGRAM_BUILD_LOG:
+            PYOPENCL_GET_STR_INFO(ProgramBuild,
+                PYOPENCL_FIRST_ARG, param_name);
 #if PYOPENCL_CL_VERSION >= 0x1020
-        case CL_PROGRAM_BINARY_TYPE:
-          PYOPENCL_GET_INTEGRAL_INFO(ProgramBuild,
-                                     PYOPENCL_FIRST_ARG, param_name,
-                                     cl_program_binary_type);
+          case CL_PROGRAM_BINARY_TYPE:
+            PYOPENCL_GET_INTEGRAL_INFO(ProgramBuild,
+                PYOPENCL_FIRST_ARG, param_name,
+                cl_program_binary_type);
 #endif
 #undef PYOPENCL_FIRST_ARG
 
-        default:
-          throw error("Program.get_build_info", CL_INVALID_VALUE);
+          default:
+            throw error("Program.get_build_info", CL_INVALID_VALUE);
         }
-    }
+      }
 
-    void build(char *options, cl_uint num_devices, void **ptr_devices)
-    {
-      // todo: this function should get a list of device instances, not raw pointers
-      // pointers are for the cffi interface and should not be here
-      std::vector<cl_device_id> devices(num_devices);
-      for(cl_uint i = 0; i < num_devices; ++i) {
-        devices[i] = static_cast<device*>(ptr_devices[i])->data();
+      void build(char *options, cl_uint num_devices, void **ptr_devices)
+      {
+        // todo: this function should get a list of device instances, not raw pointers
+        // pointers are for the cffi interface and should not be here
+        std::vector<cl_device_id> devices(num_devices);
+        for(cl_uint i = 0; i < num_devices; ++i) {
+          devices[i] = static_cast<device*>(ptr_devices[i])->data();
+        }
+        PYOPENCL_CALL_GUARDED_THREADED(clBuildProgram,
+            (m_program, num_devices, devices.empty( ) ? NULL : &devices.front(),
+             options, 0 ,0));
       }
-      PYOPENCL_CALL_GUARDED_THREADED(clBuildProgram,
-                                     (m_program, num_devices, devices.empty( ) ? NULL : &devices.front(),
-                                      options, 0 ,0));
-    }
 
-    // #if PYOPENCL_CL_VERSION >= 0x1020
-    //       void compile(std::string options, py::object py_devices,
-    //           py::object py_headers)
-    //       {
-    //         PYOPENCL_PARSE_PY_DEVICES;
+      // #if PYOPENCL_CL_VERSION >= 0x1020
+      //       void compile(std::string options, py::object py_devices,
+      //           py::object py_headers)
+      //       {
+      //         PYOPENCL_PARSE_PY_DEVICES;
+
+      //         // {{{ pick apart py_headers
+      //         // py_headers is a list of tuples *(name, program)*
+
+      //         std::vector<std::string> header_names;
+      //         std::vector<cl_program> programs;
+      //         PYTHON_FOREACH(name_hdr_tup, py_headers)
+      //         {
+      //           if (py::len(name_hdr_tup) != 2)
+      //             throw error("Program.compile", CL_INVALID_VALUE,
+      //                 "epxected (name, header) tuple in headers list");
+      //           std::string name = py::extract<std::string const &>(name_hdr_tup[0]);
+      //           program &prg = py::extract<program &>(name_hdr_tup[1]);
+
+      //           header_names.push_back(name);
+      //           programs.push_back(prg.data());
+      //         }
+
+      //         std::vector<const char *> header_name_ptrs;
+      //         BOOST_FOREACH(std::string const &name, header_names)
+      //           header_name_ptrs.push_back(name.c_str());
+
+      //         // }}}
+
+      //         PYOPENCL_CALL_GUARDED_THREADED(clCompileProgram,
+      //             (m_program, num_devices, devices,
+      //              options.c_str(), header_names.size(),
+      //              programs.empty() ? NULL : &programs.front(),
+      //              header_name_ptrs.empty() ? NULL : &header_name_ptrs.front(),
+      //              0, 0));
+      //       }
+      // #endif
+  };
 
-    //         // {{{ pick apart py_headers
-    //         // py_headers is a list of tuples *(name, program)*
 
-    //         std::vector<std::string> header_names;
-    //         std::vector<cl_program> programs;
-    //         PYTHON_FOREACH(name_hdr_tup, py_headers)
-    //         {
-    //           if (py::len(name_hdr_tup) != 2)
-    //             throw error("Program.compile", CL_INVALID_VALUE,
-    //                 "epxected (name, header) tuple in headers list");
-    //           std::string name = py::extract<std::string const &>(name_hdr_tup[0]);
-    //           program &prg = py::extract<program &>(name_hdr_tup[1]);
-
-    //           header_names.push_back(name);
-    //           programs.push_back(prg.data());
-    //         }
+  inline
+  program *create_program_with_source(
+      context &ctx,
+      std::string const &src)
+  {
+    const char *string = src.c_str();
+    size_t length = src.size();
 
-    //         std::vector<const char *> header_name_ptrs;
-    //         BOOST_FOREACH(std::string const &name, header_names)
-    //           header_name_ptrs.push_back(name.c_str());
+    cl_int status_code;
+    PYOPENCL_PRINT_CALL_TRACE("clCreateProgramWithSource");
 
-    //         // }}}
+    cl_program result = clCreateProgramWithSource(
+        ctx.data(), 1, &string, &length, &status_code);
 
-    //         PYOPENCL_CALL_GUARDED_THREADED(clCompileProgram,
-    //             (m_program, num_devices, devices,
-    //              options.c_str(), header_names.size(),
-    //              programs.empty() ? NULL : &programs.front(),
-    //              header_name_ptrs.empty() ? NULL : &header_name_ptrs.front(),
-    //              0, 0));
-    //       }
-    // #endif
-  };
+    if (status_code != CL_SUCCESS)
+      throw pyopencl::error("clCreateProgramWithSource", status_code);
+
+    try
+    {
+      return new program(result, false, KND_SOURCE);
+    }
+    catch (...)
+    {
+      clReleaseProgram(result);
+      throw;
+    }
+  }
+
+
+  inline
+  program *create_program_with_binary(
+      context &ctx,
+      cl_uint num_devices,
+      void **ptr_devices,
+      cl_uint num_binaries,
+      char **binaries,
+      size_t *binary_sizes)
+  {
+    std::vector<cl_device_id> devices;
+    std::vector<cl_int> binary_statuses(num_devices);
+    for (cl_uint i = 0; i < num_devices; ++i)
+      {
+        devices.push_back(static_cast<device*>(ptr_devices[i])->data());
+      }
+    cl_int status_code;
+    PYOPENCL_PRINT_CALL_TRACE("clCreateProgramWithBinary");
+    cl_program result = clCreateProgramWithBinary(
+        ctx.data(), num_devices,
+        devices.empty( ) ? NULL : &devices.front(),
+        binary_sizes,
+        reinterpret_cast<const unsigned char**>(const_cast<const char**>(binaries)),
+        binary_statuses.empty( ) ? NULL : &binary_statuses.front(),
+        &status_code);
+
+    // for (cl_uint i = 0; i < num_devices; ++i)
+    //   std::cout << i << ":" << binary_statuses[i] << std::endl;
+
+    if (status_code != CL_SUCCESS)
+      throw pyopencl::error("clCreateProgramWithBinary", status_code);
+
+    try
+    {
+      return new program(result, false, KND_BINARY);
+    }
+    catch (...)
+    {
+      clReleaseProgram(result);
+      throw;
+    }
+  }
 
   // }}}
 
+
   // {{{ kernel
+
   class local_memory
   {
   private:
@@ -2379,7 +2493,7 @@ namespace pyopencl
 
 
 
-  class kernel : public _common // : boost::noncopyable
+  class kernel : public noncopyable
   {
   private:
     cl_kernel m_kernel;
@@ -2418,34 +2532,34 @@ namespace pyopencl
     void set_arg_null(cl_uint arg_index)
     {
       cl_mem m = 0;
-      PYOPENCL_CALL_GUARDED(clSetKernelArg, (m_kernel, arg_index,
-                                             sizeof(cl_mem), &m));
+      PYOPENCL_CALL_GUARDED(
+          clSetKernelArg, (m_kernel, arg_index, sizeof(cl_mem), &m));
     }
 
     void set_arg_mem(cl_uint arg_index, memory_object_holder &moh)
     {
       cl_mem m = moh.data();
-      PYOPENCL_CALL_GUARDED(clSetKernelArg,
-                            (m_kernel, arg_index, sizeof(cl_mem), &m));
+      PYOPENCL_CALL_GUARDED(
+          clSetKernelArg, (m_kernel, arg_index, sizeof(cl_mem), &m));
     }
 
     void set_arg_local(cl_uint arg_index, local_memory const &loc)
     {
-      PYOPENCL_CALL_GUARDED(clSetKernelArg,
-                            (m_kernel, arg_index, loc.size(), 0));
+      PYOPENCL_CALL_GUARDED(
+          clSetKernelArg, (m_kernel, arg_index, loc.size(), 0));
     }
 
     void set_arg_sampler(cl_uint arg_index, sampler const &smp)
     {
       cl_sampler s = smp.data();
-      PYOPENCL_CALL_GUARDED(clSetKernelArg,
-                            (m_kernel, arg_index, sizeof(cl_sampler), &s));
+      PYOPENCL_CALL_GUARDED(
+          clSetKernelArg, (m_kernel, arg_index, sizeof(cl_sampler), &s));
     }
 
     void set_arg_buf(cl_uint arg_index, void *buffer, size_t size)
     {
-      PYOPENCL_CALL_GUARDED(clSetKernelArg,
-                            (m_kernel, arg_index, size, buffer));
+      PYOPENCL_CALL_GUARDED(
+          clSetKernelArg, (m_kernel, arg_index, size, buffer));
     }
 
     // void set_arg(cl_uint arg_index, py::object arg)
@@ -2574,6 +2688,7 @@ namespace pyopencl
 
   // }}}
 
+
   // {{{ buffer transfers
 
   inline
@@ -2673,16 +2788,17 @@ namespace pyopencl
 
   // }}}
 
+
   inline event *enqueue_nd_range_kernel(
-                                        command_queue &cq,
-                                        kernel &knl,
-                                        cl_uint work_dim,
-                                        const size_t *global_work_offset,
-                                        const size_t *global_work_size,
-                                        const size_t *local_work_size //,
-                                        //py::object py_global_work_offset,
-                                        //py::object py_wait_for,
-                                        )
+      command_queue &cq,
+      kernel &knl,
+      cl_uint work_dim,
+      const size_t *global_work_offset,
+      const size_t *global_work_size,
+      const size_t *local_work_size //,
+      //py::object py_global_work_offset,
+      //py::object py_wait_for,
+      )
   {
     // TODO
     // PYOPENCL_PARSE_WAIT_FOR;
@@ -2701,334 +2817,503 @@ namespace pyopencl
                            &evt
                            ));
     PYOPENCL_RETURN_NEW_EVENT(evt);
-
   }
+}
 
 
-  inline
-  program *create_program_with_source(
-                                      context &ctx,
-                                      std::string const &src)
-  {
-    const char *string = src.c_str();
-    size_t length = src.size();
+// {{{ c wrapper
 
-    cl_int status_code;
-    PYOPENCL_PRINT_CALL_TRACE("clCreateProgramWithSource");
-    cl_program result = clCreateProgramWithSource(
-                                                  ctx.data(), 1, &string, &length, &status_code);
-    if (status_code != CL_SUCCESS)
-      throw pyopencl::error("clCreateProgramWithSource", status_code);
+void free_pointer(void *p)
+{
+  free(p);
+}
 
-    try
-      {
-        return new program(result, false, KND_SOURCE);
-      }
-    catch (...)
-      {
-        clReleaseProgram(result);
-        throw;
-      }
-  }
+void free_pointer_array(void **p, uint32_t size)
+{
+  for(uint32_t i = 0; i < size; ++i)
+    free_pointer(p[i]);
+}
 
-  inline
-  program *create_program_with_binary(context &ctx,
-                                      cl_uint num_devices,
-                                      void **ptr_devices,
-                                      cl_uint num_binaries,
-                                      char **binaries,
-                                      size_t *binary_sizes)
-  {
-    std::vector<cl_device_id> devices;
-    std::vector<cl_int> binary_statuses(num_devices);
-    for (cl_uint i = 0; i < num_devices; ++i)
-      {
-        devices.push_back(static_cast<device*>(ptr_devices[i])->data());
-      }
-    cl_int status_code;
-    PYOPENCL_PRINT_CALL_TRACE("clCreateProgramWithBinary");
-    cl_program result = clCreateProgramWithBinary(ctx.data(), num_devices,
-                                                  devices.empty( ) ? NULL : &devices.front(),
-                                                  binary_sizes,
-                                                  reinterpret_cast<const unsigned char**>(const_cast<const char**>(binaries)),
-                                                  binary_statuses.empty( ) ? NULL : &binary_statuses.front(),
-                                                  &status_code);
 
-    // for (cl_uint i = 0; i < num_devices; ++i)
-    //   std::cout << i << ":" << binary_statuses[i] << std::endl;
-    if (status_code != CL_SUCCESS)
-      throw pyopencl::error("clCreateProgramWithBinary", status_code);
+::error *get_platforms(void **ptr_platforms, uint32_t *num_platforms)
+{
+  BEGIN_C_HANDLE_ERROR
 
-    try
-      {
-        return new program(result, false, KND_BINARY);
-      }
-    catch (...)
-      {
-        clReleaseProgram(result);
-        throw;
-      }
-  }
+  *num_platforms = 0;
+  PYOPENCL_CALL_GUARDED(clGetPlatformIDs, (0, 0, num_platforms));
 
+  typedef std::vector<cl_platform_id> vec;
+  vec platforms(*num_platforms);
+  PYOPENCL_CALL_GUARDED(clGetPlatformIDs,
+      (*num_platforms, platforms.empty( ) ? NULL : &platforms.front(), num_platforms));
 
+  MALLOC(pyopencl::platform*, _ptr_platforms, *num_platforms);
+  for(vec::size_type i = 0; i < platforms.size(); ++i) {
+    _ptr_platforms[i] = new pyopencl::platform(platforms[i]);
+  }
+  *ptr_platforms = _ptr_platforms;
+
+  END_C_HANDLE_ERROR
 
+  return 0;
 }
 
 
+::error *platform__get_devices(
+    void *ptr_platform,
+    void **ptr_devices,
+    uint32_t *num_devices,
+    cl_device_type devtype)
+{
+  typedef std::vector<cl_device_id> vec;
+
+  BEGIN_C_HANDLE_ERROR
 
+  vec devices = static_cast<pyopencl::platform*>(ptr_platform)->get_devices(devtype);
+  *num_devices = devices.size();
 
-::error *get_platforms(void **ptr_platforms, uint32_t *num_platforms) {
-  C_HANDLE_ERROR(
-                 *num_platforms = 0;
-                 PYOPENCL_CALL_GUARDED(clGetPlatformIDs, (0, 0, num_platforms));
+  MALLOC(pyopencl::device*, _ptr_devices, *num_devices);
+  for(vec::size_type i = 0; i < devices.size(); ++i) {
+    _ptr_devices[i] = new pyopencl::device(devices[i]);
+  }
+  *ptr_devices = _ptr_devices;
 
-                 typedef std::vector<cl_platform_id> vec;
-                 vec platforms(*num_platforms);
-                 PYOPENCL_CALL_GUARDED(clGetPlatformIDs,
-                                       (*num_platforms, platforms.empty( ) ? NULL : &platforms.front(), num_platforms));
+  END_C_HANDLE_ERROR
 
-                 MALLOC(pyopencl::platform*, _ptr_platforms, *num_platforms);
-                 for(vec::size_type i = 0; i < platforms.size(); ++i) {
-                   _ptr_platforms[i] = new pyopencl::platform(platforms[i]);
-                 }
-                 *ptr_platforms = _ptr_platforms;
-                 );
   return 0;
 }
 
-void _free(void *p) {
-  free(p);
-}
 
-void _free2(void **p, uint32_t size) {
-  for(uint32_t i = 0; i < size; ++i) {
-    _free(p[i]);
+::error *_create_context(
+    void **ptr_ctx,
+    cl_context_properties *properties,
+    cl_uint num_devices,
+    void **ptr_devices)
+{
+  BEGIN_C_HANDLE_ERROR
+
+  cl_int status_code;
+  std::vector<cl_device_id> devices(num_devices);
+  for(cl_uint i = 0; i < num_devices; ++i) {
+    devices[i] = static_cast<pyopencl::device*>(ptr_devices[i])->data();
   }
-}
+  cl_context ctx = clCreateContext(properties,
+                                   num_devices,
+                                   devices.empty() ? NULL : &devices.front(),
+                                   0, 0, &status_code);
+  if (status_code != CL_SUCCESS) {
+    throw pyopencl::error("Context", status_code);
+  }
+  *ptr_ctx = new pyopencl::context(ctx, false);
 
+  END_C_HANDLE_ERROR
 
-::error *platform__get_devices(void *ptr_platform, void **ptr_devices, uint32_t *num_devices, cl_device_type devtype) {
-  typedef std::vector<cl_device_id> vec;
-  C_HANDLE_ERROR(vec devices = static_cast<pyopencl::platform*>(ptr_platform)->get_devices(devtype);
-                 *num_devices = devices.size();
-
-                 MALLOC(pyopencl::device*, _ptr_devices, *num_devices);
-                 for(vec::size_type i = 0; i < devices.size(); ++i) {
-                   _ptr_devices[i] = new pyopencl::device(devices[i]);
-                 }
-                 *ptr_devices = _ptr_devices;
-                 );
   return 0;
 }
 
 
-::error *_create_context(void **ptr_ctx, cl_context_properties *properties, cl_uint num_devices, void **ptr_devices) {
-  C_HANDLE_ERROR(
-                 cl_int status_code;
-                 std::vector<cl_device_id> devices(num_devices);
-                 for(cl_uint i = 0; i < num_devices; ++i) {
-                   devices[i] = static_cast<pyopencl::device*>(ptr_devices[i])->data();
-                 }
-                 cl_context ctx = clCreateContext(properties,
-                                                  num_devices,
-                                                  devices.empty() ? NULL : &devices.front(),
-                                                  0, 0, &status_code);
-                 if (status_code != CL_SUCCESS) {
-                   throw pyopencl::error("Context", status_code);
-                 }
-                 *ptr_ctx = new pyopencl::context(ctx, false);
-                 );
-  return 0;
-}
-
-::error *_create_command_queue(void **ptr_command_queue, void *ptr_context, void *ptr_device, cl_command_queue_properties properties) {
+::error *_create_command_queue(
+    void **ptr_command_queue, void *ptr_context, void *ptr_device, cl_command_queue_properties properties)
+{
   pyopencl::context *ctx = static_cast<pyopencl::context*>(ptr_context);
   pyopencl::device *dev = static_cast<pyopencl::device*>(ptr_device);
-  C_HANDLE_ERROR(
-                 *ptr_command_queue = new pyopencl::command_queue(*ctx, dev, properties);
-                 );
+  BEGIN_C_HANDLE_ERROR
+
+  *ptr_command_queue = new pyopencl::command_queue(*ctx, dev, properties);
+
+  END_C_HANDLE_ERROR
+
   return 0;
 }
 
-::error *_create_buffer(void **ptr_buffer, void *ptr_context, cl_mem_flags flags, size_t size, void *hostbuf) {
+
+::error *_create_buffer(
+    void **ptr_buffer, void *ptr_context, cl_mem_flags flags,
+    size_t size, void *hostbuf)
+{
   pyopencl::context *ctx = static_cast<pyopencl::context*>(ptr_context);
-  C_HANDLE_ERROR(
-                 *ptr_buffer = create_buffer_py(*ctx, flags, size, hostbuf);
-                 );
+
+  BEGIN_C_HANDLE_ERROR
+
+  *ptr_buffer = create_buffer_py(*ctx, flags, size, hostbuf);
+
+  END_C_HANDLE_ERROR
   return 0;
 }
 
-::error *_create_program_with_source(void **ptr_program, void *ptr_context, char *src) {
+// {{{ program
+
+::error *_create_program_with_source(void **ptr_program, void *ptr_context, char *src)
+{
   pyopencl::context *ctx = static_cast<pyopencl::context*>(ptr_context);
-  C_HANDLE_ERROR(
+
+  BEGIN_C_HANDLE_ERROR
+
                  *ptr_program = create_program_with_source(*ctx, src);
-                 );
+
+  END_C_HANDLE_ERROR
+
   return 0;
 }
 
-::error *_create_program_with_binary(void **ptr_program, void *ptr_context, cl_uint num_devices, void **ptr_devices, cl_uint num_binaries, char **binaries, size_t *binary_sizes) {
+::error *_create_program_with_binary(
+    void **ptr_program, void *ptr_context, cl_uint num_devices, void **ptr_devices, cl_uint num_binaries, char **binaries, size_t *binary_sizes)
+{
   pyopencl::context *ctx = static_cast<pyopencl::context*>(ptr_context);
-  C_HANDLE_ERROR(
-                 *ptr_program = create_program_with_binary(*ctx, num_devices, ptr_devices, num_binaries, reinterpret_cast<char **>(binaries), binary_sizes);
-                 );
+
+  BEGIN_C_HANDLE_ERROR
+
+  *ptr_program = create_program_with_binary(*ctx, num_devices, ptr_devices, num_binaries, reinterpret_cast<char **>(binaries), binary_sizes);
+
+  END_C_HANDLE_ERROR
+
   return 0;
 }
 
-::error *program__build(void *ptr_program, char *options, cl_uint num_devices, void **ptr_devices) {
-  C_HANDLE_ERROR(
-                 static_cast<pyopencl::program*>(ptr_program)->build(options, num_devices, ptr_devices);
-                 );
+::error *program__build(
+    void *ptr_program, char *options, cl_uint num_devices, void **ptr_devices)
+{
+
+  BEGIN_C_HANDLE_ERROR
+
+  static_cast<pyopencl::program*>(ptr_program)->build(options, num_devices, ptr_devices);
+
+  END_C_HANDLE_ERROR
+
   return 0;
 }
 
-::error *program__kind(void *ptr_program, int *kind) {
-  C_HANDLE_ERROR(
-                 *kind = static_cast<pyopencl::program*>(ptr_program)->kind();
-                 );
+::error *program__kind(void *ptr_program, int *kind)
+{
+  BEGIN_C_HANDLE_ERROR
+
+  *kind = static_cast<pyopencl::program*>(ptr_program)->kind();
+
+  END_C_HANDLE_ERROR
+
   return 0;
 }
 
 
-::error *program__get_build_info(void *ptr_program, void *ptr_device, cl_program_build_info param, generic_info *out) {
-  C_HANDLE_ERROR(
-                 *out = static_cast<pyopencl::program*>(ptr_program)->get_build_info(*static_cast<pyopencl::device*>(ptr_device),
-                                                                                     param);
-                 );
+::error *program__get_build_info(
+    void *ptr_program, void *ptr_device, cl_program_build_info param, generic_info *out)
+{
+  BEGIN_C_HANDLE_ERROR
+
+  *out = static_cast<pyopencl::program*>(ptr_program)
+    ->get_build_info(
+        *static_cast<pyopencl::device*>(ptr_device),
+        param);
+
+  END_C_HANDLE_ERROR
+
   return 0;
 }
 
-::error *_create_sampler(void **ptr_sampler, void *ptr_context, int normalized_coordinates, cl_addressing_mode am, cl_filter_mode fm) {
-  C_HANDLE_ERROR(*ptr_sampler = new pyopencl::sampler(*static_cast<pyopencl::context*>(ptr_context), (bool)normalized_coordinates, am, fm););
+// }}}
+
+
+::error *_create_sampler(
+    void **ptr_sampler, void *ptr_context, int normalized_coordinates,
+    cl_addressing_mode am, cl_filter_mode fm)
+{
+  BEGIN_C_HANDLE_ERROR
+
+  *ptr_sampler = new pyopencl::sampler(
+      *static_cast<pyopencl::context*>(ptr_context),
+      (bool)normalized_coordinates, am, fm);
+
+  END_C_HANDLE_ERROR
+
   return 0;
 }
 
 
-::error *event__get_profiling_info(void *ptr, cl_profiling_info param, generic_info *out) {
-  C_HANDLE_ERROR(*out = static_cast<pyopencl::event*>(ptr)->get_profiling_info(param););
+// {{{ event
+
+::error *event__get_profiling_info(
+    void *ptr, cl_profiling_info param, generic_info *out)
+{
+  BEGIN_C_HANDLE_ERROR
+
+  *out = static_cast<pyopencl::event*>(ptr)->get_profiling_info(param);
+
+  END_C_HANDLE_ERROR
+
   return 0;
 }
 
-::error *event__wait(void *ptr) {
-  C_HANDLE_ERROR(static_cast<pyopencl::event*>(ptr)->wait(););
+::error *event__wait(void *ptr)
+{
+  BEGIN_C_HANDLE_ERROR
+
+      static_cast<pyopencl::event*>(ptr)->wait();
+
+  END_C_HANDLE_ERROR
+
   return 0;
 }
 
+// }}}
+
+
+// {{{ kernel
+
 ::error *_create_kernel(void **ptr_kernel, void *ptr_program, char *name) {
   pyopencl::program *prg = static_cast<pyopencl::program*>(ptr_program);
-  C_HANDLE_ERROR(
-                 *ptr_kernel = new pyopencl::kernel(*prg, name);
-                 );
+
+  BEGIN_C_HANDLE_ERROR
+
+  *ptr_kernel = new pyopencl::kernel(*prg, name);
+
+  END_C_HANDLE_ERROR
+
   return 0;
 }
 
-::error *kernel__set_arg_null(void *ptr_kernel, cl_uint arg_index) {
-  C_HANDLE_ERROR(static_cast<pyopencl::kernel*>(ptr_kernel)->set_arg_null(arg_index););
+::error *kernel__set_arg_null(void *ptr_kernel, cl_uint arg_index)
+{
+  BEGIN_C_HANDLE_ERROR
+
+  static_cast<pyopencl::kernel*>(ptr_kernel)->set_arg_null(arg_index);
+
+  END_C_HANDLE_ERROR
+
   return 0;
 }
 
-::error *kernel__set_arg_mem(void *ptr_kernel, cl_uint arg_index, void *ptr_mem) {
-  pyopencl::memory_object_holder *mem = static_cast<pyopencl::memory_object_holder*>(ptr_mem);
-  C_HANDLE_ERROR(static_cast<pyopencl::kernel*>(ptr_kernel)->set_arg_mem(arg_index, *mem););
+::error *kernel__set_arg_mem(void *ptr_kernel, cl_uint arg_index, void *ptr_mem)
+{
+  pyopencl::memory_object_holder *mem =
+    static_cast<pyopencl::memory_object_holder*>(ptr_mem);
+
+  BEGIN_C_HANDLE_ERROR
+
+  static_cast<pyopencl::kernel*>(ptr_kernel)->set_arg_mem(arg_index, *mem);
+
+  END_C_HANDLE_ERROR
+
   return 0;
 }
 
 ::error *kernel__set_arg_sampler(void *ptr_kernel, cl_uint arg_index, void *ptr_sampler) {
   pyopencl::sampler *sampler = static_cast<pyopencl::sampler*>(ptr_sampler);
-  C_HANDLE_ERROR(static_cast<pyopencl::kernel*>(ptr_kernel)->set_arg_sampler(arg_index, *sampler););
+
+  BEGIN_C_HANDLE_ERROR
+
+  static_cast<pyopencl::kernel*>(ptr_kernel)->set_arg_sampler(arg_index, *sampler);
+
+  END_C_HANDLE_ERROR
+
   return 0;
 }
 
-::error *kernel__set_arg_buf(void *ptr_kernel, cl_uint arg_index, void *buffer, size_t size) {
-  C_HANDLE_ERROR(static_cast<pyopencl::kernel*>(ptr_kernel)->set_arg_buf(arg_index, buffer, size););
+::error *kernel__set_arg_buf(
+    void *ptr_kernel, cl_uint arg_index, void *buffer, size_t size)
+{
+  BEGIN_C_HANDLE_ERROR
+
+  static_cast<pyopencl::kernel*>(ptr_kernel)->set_arg_buf(arg_index, buffer, size);
+
+  END_C_HANDLE_ERROR
+
   return 0;
 }
 
 
-::error *kernel__get_work_group_info(void *ptr, cl_kernel_work_group_info param, void *ptr_device, generic_info *out) {
-  C_HANDLE_ERROR(*out = static_cast<pyopencl::kernel*>(ptr)->get_work_group_info(param, *static_cast<pyopencl::device*>(ptr_device)););
+::error *kernel__get_work_group_info(
+    void *ptr, cl_kernel_work_group_info param, void *ptr_device, generic_info *out)
+{
+  BEGIN_C_HANDLE_ERROR
+
+      *out = static_cast<pyopencl::kernel*>(ptr)->get_work_group_info(param, *static_cast<pyopencl::device*>(ptr_device));
+
+  END_C_HANDLE_ERROR
+
   return 0;
 }
 
-::error *_get_supported_image_formats(void *ptr_context, cl_mem_flags flags, cl_mem_object_type image_type, generic_info *out) {
-  C_HANDLE_ERROR(*out = get_supported_image_formats(*static_cast<pyopencl::context*>(ptr_context), flags, image_type););
+// }}}
+
+
+// {{{ image
+
+::error *_get_supported_image_formats(
+    void *ptr_context, cl_mem_flags flags, cl_mem_object_type image_type, generic_info *out)
+{
+  BEGIN_C_HANDLE_ERROR
+
+  *out = get_supported_image_formats(*static_cast<pyopencl::context*>(ptr_context), flags, image_type);
+
+  END_C_HANDLE_ERROR
+
   return 0;
 }
 
-error *_create_image_2d(void **ptr_image, void *ptr_context, cl_mem_flags flags, cl_image_format *fmt, size_t width, size_t height, size_t pitch, void *ptr_buffer, size_t size) {
-  C_HANDLE_ERROR(*ptr_image = create_image_2d(*static_cast<pyopencl::context*>(ptr_context), flags, *fmt, width, height, pitch, ptr_buffer, size););
+error *_create_image_2d(
+    void **ptr_image, void *ptr_context, cl_mem_flags flags,
+    cl_image_format *fmt, size_t width, size_t height, size_t pitch,
+    void *ptr_buffer, size_t size)
+{
+  BEGIN_C_HANDLE_ERROR
+
+  *ptr_image = create_image_2d(
+      *static_cast<pyopencl::context*>(ptr_context), flags, *fmt,
+      width, height, pitch, ptr_buffer, size);
+
+  END_C_HANDLE_ERROR
+
   return 0;
 }
 
 
-error *_create_image_3d(void **ptr_image, void *ptr_context, cl_mem_flags flags, cl_image_format *fmt, size_t width, size_t height, size_t depth, size_t pitch_x, size_t pitch_y, void *ptr_buffer, size_t size) {
-  C_HANDLE_ERROR(*ptr_image = create_image_3d(*static_cast<pyopencl::context*>(ptr_context), flags, *fmt, width, height, depth, pitch_x, pitch_y, ptr_buffer, size););
+error *_create_image_3d(
+    void **ptr_image, void *ptr_context, cl_mem_flags flags,
+    cl_image_format *fmt, size_t width, size_t height, size_t depth,
+    size_t pitch_x, size_t pitch_y, void *ptr_buffer, size_t size)
+{
+  BEGIN_C_HANDLE_ERROR
+
+  *ptr_image = create_image_3d(
+      *static_cast<pyopencl::context*>(ptr_context),
+      flags, *fmt, width, height, depth, pitch_x, pitch_y, ptr_buffer, size);
+
+  END_C_HANDLE_ERROR
+
   return 0;
 }
 
-::error *image__get_image_info(void *ptr, cl_image_info param, generic_info *out) {
-  C_HANDLE_ERROR(*out = static_cast<pyopencl::image*>(ptr)->get_image_info(param););
+
+::error *image__get_image_info(void *ptr, cl_image_info param, generic_info *out)
+{
+  BEGIN_C_HANDLE_ERROR
+
+  *out = static_cast<pyopencl::image*>(ptr)->get_image_info(param);
+
+  END_C_HANDLE_ERROR
+
   return 0;
 }
 
+// }}}
+
+
+::error *_enqueue_nd_range_kernel(
+    void **ptr_event, void *ptr_command_queue, void *ptr_kernel,
+    cl_uint work_dim, const size_t *global_work_offset,
+    const size_t *global_work_size, const size_t *local_work_size)
+{
+  BEGIN_C_HANDLE_ERROR
+
+  *ptr_event = enqueue_nd_range_kernel(
+      *static_cast<pyopencl::command_queue*>(ptr_command_queue),
+      *static_cast<pyopencl::kernel*>(ptr_kernel),
+      work_dim,
+      global_work_offset,
+      global_work_size,
+      local_work_size);
+
+  END_C_HANDLE_ERROR
 
-::error *_enqueue_nd_range_kernel(void **ptr_event, void *ptr_command_queue, void *ptr_kernel, cl_uint work_dim, const size_t *global_work_offset, const size_t *global_work_size, const size_t *local_work_size) {
-  C_HANDLE_ERROR(
-                 *ptr_event = enqueue_nd_range_kernel(*static_cast<pyopencl::command_queue*>(ptr_command_queue),
-                                                      *static_cast<pyopencl::kernel*>(ptr_kernel),
-                                                      work_dim,
-                                                      global_work_offset,
-                                                      global_work_size,
-                                                      local_work_size);
-                 );
   return 0;
 }
 
+// {{{ transfer enqueues
+
+::error *_enqueue_read_buffer(
+    void **ptr_event, void *ptr_command_queue, void *ptr_memory_object_holder,
+    void *buffer, size_t size, size_t device_offset, void **wait_for,
+    uint32_t num_wait_for, int is_blocking)
+{
+  BEGIN_C_HANDLE_ERROR
+
+  *ptr_event = enqueue_read_buffer(
+      *static_cast<pyopencl::command_queue*>(ptr_command_queue),
+      *static_cast<pyopencl::memory_object_holder*>(ptr_memory_object_holder),
+      buffer, size, device_offset, wait_for, num_wait_for, (bool)is_blocking);
+
+  END_C_HANDLE_ERROR
 
-::error *_enqueue_read_buffer(void **ptr_event, void *ptr_command_queue, void *ptr_memory_object_holder, void *buffer, size_t size, size_t device_offset, void **wait_for, uint32_t num_wait_for, int is_blocking) {
-  C_HANDLE_ERROR(*ptr_event = enqueue_read_buffer(*static_cast<pyopencl::command_queue*>(ptr_command_queue),
-                                                  *static_cast<pyopencl::memory_object_holder*>(ptr_memory_object_holder),
-                                                  buffer, size, device_offset, wait_for, num_wait_for, (bool)is_blocking);
-                 );
   return 0;
 }
 
-::error *_enqueue_write_buffer(void **ptr_event, void *ptr_command_queue, void *ptr_mem, void *buffer, size_t size, size_t device_offset, void **wait_for, uint32_t num_wait_for, int is_blocking) {
-  C_HANDLE_ERROR(*ptr_event = enqueue_write_buffer(*static_cast<pyopencl::command_queue*>(ptr_command_queue),
-                                                   *static_cast<pyopencl::memory_object_holder*>(ptr_mem),
-                                                   buffer, size, device_offset, wait_for, num_wait_for, (bool)is_blocking);
-                 );
+
+
+::error *_enqueue_write_buffer(
+    void **ptr_event, void *ptr_command_queue, void *ptr_mem,
+    void *buffer, size_t size, size_t device_offset, void **wait_for,
+    uint32_t num_wait_for, int is_blocking)
+{
+  BEGIN_C_HANDLE_ERROR
+
+  *ptr_event = enqueue_write_buffer(
+      *static_cast<pyopencl::command_queue*>(ptr_command_queue),
+      *static_cast<pyopencl::memory_object_holder*>(ptr_mem),
+      buffer, size, device_offset, wait_for, num_wait_for, (bool)is_blocking);
+
+  END_C_HANDLE_ERROR
+
   return 0;
 }
 
-::error *_enqueue_copy_buffer(void **ptr_event, void *ptr_command_queue, void *ptr_src, void *ptr_dst, ptrdiff_t byte_count, size_t src_offset, size_t dst_offset, void **wait_for, uint32_t num_wait_for) {
-  C_HANDLE_ERROR(*ptr_event = enqueue_copy_buffer(*static_cast<pyopencl::command_queue*>(ptr_command_queue),
-                                                  *static_cast<pyopencl::memory_object_holder*>(ptr_src),
-                                                  *static_cast<pyopencl::memory_object_holder*>(ptr_dst),
-                                                  byte_count, src_offset, dst_offset, wait_for, num_wait_for);
-                 );
+
+::error *_enqueue_copy_buffer(
+    void **ptr_event, void *ptr_command_queue, void *ptr_src,
+    void *ptr_dst, ptrdiff_t byte_count, size_t src_offset, size_t dst_offset,
+    void **wait_for, uint32_t num_wait_for)
+{
+  BEGIN_C_HANDLE_ERROR
+
+  *ptr_event = enqueue_copy_buffer(
+      *static_cast<pyopencl::command_queue*>(ptr_command_queue),
+      *static_cast<pyopencl::memory_object_holder*>(ptr_src),
+      *static_cast<pyopencl::memory_object_holder*>(ptr_dst),
+      byte_count, src_offset, dst_offset, wait_for, num_wait_for);
+
+  END_C_HANDLE_ERROR
+
   return 0;
 }
 
-::error *_enqueue_read_image(void **ptr_event, void *ptr_command_queue, void *ptr_mem, size_t *origin, size_t *region, void *buffer, size_t size, size_t row_pitch, size_t slice_pitch, void **wait_for, uint32_t num_wait_for, int is_blocking) {
-  C_HANDLE_ERROR(*ptr_event = enqueue_read_image(*static_cast<pyopencl::command_queue*>(ptr_command_queue),
-                                                  *static_cast<pyopencl::image*>(ptr_mem),
-                                                 origin, region, buffer, size, row_pitch, slice_pitch, wait_for, num_wait_for, (bool)is_blocking);
-                 );
+
+::error *_enqueue_read_image(
+    void **ptr_event, void *ptr_command_queue, void *ptr_mem,
+    size_t *origin, size_t *region, void *buffer, size_t size, size_t row_pitch,
+    size_t slice_pitch, void **wait_for, uint32_t num_wait_for, int is_blocking)
+{
+  BEGIN_C_HANDLE_ERROR
+
+  *ptr_event = enqueue_read_image(
+      *static_cast<pyopencl::command_queue*>(ptr_command_queue),
+      *static_cast<pyopencl::image*>(ptr_mem),
+      origin, region, buffer, size, row_pitch, slice_pitch, wait_for, num_wait_for,
+      (bool)is_blocking);
+
+  END_C_HANDLE_ERROR
+
   return 0;
 }
 
+// }}}
+
 
 intptr_t _int_ptr(void* ptr, class_t class_) {
 #define INT_PTR(CLSU, CLS) return (intptr_t)(static_cast<pyopencl::CLS*>(ptr)->data());
   SWITCHCLASS(INT_PTR);
 }
 
+
 void* _from_int_ptr(void **ptr_out, intptr_t int_ptr_value, class_t class_) {
-#define FROM_INT_PTR(CLSU, CLS) C_HANDLE_ERROR(*ptr_out = new pyopencl::CLS((PYOPENCL_CL_##CLSU)int_ptr_value, /* retain */ true);)
+#define FROM_INT_PTR(CLSU, CLS) \
+  BEGIN_C_HANDLE_ERROR \
+  *ptr_out = new pyopencl::CLS((PYOPENCL_CL_##CLSU)int_ptr_value, /* retain */ true); \
+  END_C_HANDLE_ERROR
+
   SWITCHCLASS(FROM_INT_PTR);
   return 0;
 }
 
+
 long _hash(void *ptr, class_t class_) {
 #define HASH(CLSU, CLS) return static_cast<pyopencl::CLS*>(ptr)->hash();
   SWITCHCLASS(HASH);
@@ -3036,7 +3321,11 @@ long _hash(void *ptr, class_t class_) {
 
 
 ::error *_get_info(void *ptr, class_t class_, cl_uint param, generic_info *out) {
-#define GET_INFO(CLSU, CLS) C_HANDLE_ERROR(*out = static_cast<pyopencl::CLS*>(ptr)->get_info(param);)
+#define GET_INFO(CLSU, CLS) \
+    BEGIN_C_HANDLE_ERROR \
+    *out = static_cast<pyopencl::CLS*>(ptr)->get_info(param); \
+    END_C_HANDLE_ERROR
+
   SWITCHCLASS(GET_INFO);
   return 0;
 }
@@ -3051,11 +3340,8 @@ int get_cl_version(void) {
   return PYOPENCL_CL_VERSION;
 }
 
-unsigned bitlog2(unsigned long v) {
-  return pyopencl::bitlog2(v);
-}
-
 // {{{ gl interop
+
 int have_gl() {
 #ifdef HAVE_GL
   return 1;
@@ -3064,35 +3350,73 @@ int have_gl() {
 #endif
 }
 
-error *_create_from_gl_buffer(void **ptr, void *ptr_context, cl_mem_flags flags, GLuint bufobj) {
+
+error *_create_from_gl_buffer(
+    void **ptr, void *ptr_context, cl_mem_flags flags, GLuint bufobj)
+{
   pyopencl::context *ctx = static_cast<pyopencl::context*>(ptr_context);
-  C_HANDLE_ERROR(*ptr = create_from_gl_buffer(*ctx, flags, bufobj););
+
+  BEGIN_C_HANDLE_ERROR
+
+  *ptr = create_from_gl_buffer(*ctx, flags, bufobj);
+
+  END_C_HANDLE_ERROR
+
   return 0;
 }
 
-error *_create_from_gl_renderbuffer(void **ptr, void *ptr_context, cl_mem_flags flags, GLuint bufobj) {
+
+error *_create_from_gl_renderbuffer(
+    void **ptr, void *ptr_context, cl_mem_flags flags, GLuint bufobj)
+{
   pyopencl::context *ctx = static_cast<pyopencl::context*>(ptr_context);
-  C_HANDLE_ERROR(*ptr = create_from_gl_renderbuffer(*ctx, flags, bufobj););
+
+  BEGIN_C_HANDLE_ERROR
+
+  *ptr = create_from_gl_renderbuffer(*ctx, flags, bufobj);
+
+  END_C_HANDLE_ERROR
+
   return 0;
 }
 
-::error *_enqueue_acquire_gl_objects(void **ptr_event, void *ptr_command_queue, void **ptr_mem_objects, uint32_t num_mem_objects, void **wait_for, uint32_t num_wait_for) {
-  C_HANDLE_ERROR(
-                 *ptr_event = enqueue_acquire_gl_objects(*static_cast<pyopencl::command_queue*>(ptr_command_queue),
-                                                         ptr_mem_objects, num_mem_objects,
-                                                         wait_for, num_wait_for);
-                 );
+
+::error *_enqueue_acquire_gl_objects(
+    void **ptr_event, void *ptr_command_queue,
+    void **ptr_mem_objects, uint32_t num_mem_objects, void **wait_for,
+    uint32_t num_wait_for)
+{
+  BEGIN_C_HANDLE_ERROR
+
+    *ptr_event = enqueue_acquire_gl_objects(
+        *static_cast<pyopencl::command_queue*>(ptr_command_queue),
+        ptr_mem_objects, num_mem_objects,
+        wait_for, num_wait_for);
+
+  END_C_HANDLE_ERROR
+
   return 0;
 }
 
-::error *_enqueue_release_gl_objects(void **ptr_event, void *ptr_command_queue, void **ptr_mem_objects, uint32_t num_mem_objects, void **wait_for, uint32_t num_wait_for) {
-  C_HANDLE_ERROR(
-                 *ptr_event = enqueue_release_gl_objects(*static_cast<pyopencl::command_queue*>(ptr_command_queue),
-                                                         ptr_mem_objects, num_mem_objects,
-                                                         wait_for, num_wait_for);
-                 );
+
+::error *_enqueue_release_gl_objects(
+    void **ptr_event, void *ptr_command_queue, void **ptr_mem_objects,
+    uint32_t num_mem_objects, void **wait_for, uint32_t num_wait_for)
+{
+  BEGIN_C_HANDLE_ERROR
+
+  *ptr_event = enqueue_release_gl_objects(
+      *static_cast<pyopencl::command_queue*>(ptr_command_queue),
+      ptr_mem_objects, num_mem_objects,
+      wait_for, num_wait_for);
+
+  END_C_HANDLE_ERROR
+
   return 0;
 }
 
+// }}}
 
 // }}}
+
+// vim: foldmethod=marker
diff --git a/src/wrapper/_pvt_struct_v2.cpp b/src/wrapper/_pvt_struct_v2.cpp
deleted file mode 100644
index 23a40781..00000000
--- a/src/wrapper/_pvt_struct_v2.cpp
+++ /dev/null
@@ -1,1613 +0,0 @@
-/* struct module -- pack values into and (out of) strings */
-
-/* New version supporting byte order, alignment and size options,
-   character strings, and unsigned numbers */
-
-/* Compared with vanilla Python's struct module, this adds support
- * for packing complex values and only supports native packing.
- * (the minimum that's needed for PyOpenCL.) */
-
-#define PY_SSIZE_T_CLEAN
-
-#include "Python.h"
-#include "structseq.h"
-#include "structmember.h"
-#include <ctype.h>
-#include "numpy_init.hpp"
-
-// static PyTypeObject PyStructType;
-
-/* compatibility macros */
-#if (PY_VERSION_HEX < 0x02050000)
-#ifndef PY_SSIZE_T_MIN
-typedef long int Py_ssize_t;
-#endif
-
-#define PyInt_FromSsize_t(x) PyInt_FromLong(x)
-#define PyInt_AsSsize_t(x) PyInt_AsLong(x)
-#endif
-
-/* If PY_STRUCT_FLOAT_COERCE is defined, the struct module will allow float
-   arguments for integer formats with a warning for backwards
-   compatibility. */
-
-#define PY_STRUCT_FLOAT_COERCE 1
-
-#ifdef PY_STRUCT_FLOAT_COERCE
-#define FLOAT_COERCE "integer argument expected, got float"
-#endif
-
-/* Compatibility with Py2.5 and older */
-
-#ifndef Py_TYPE
-#  define Py_TYPE(o) ((o)->ob_type)
-#endif
-
-#ifndef PyVarObject_HEAD_INIT
-#define PyVarObject_HEAD_INIT(type, size)       \
-          PyObject_HEAD_INIT(type) size,
-#endif
-
-#ifndef SIZEOF_SIZE_T
-#define SIZEOF_SIZE_T sizeof(size_t)
-#endif
-
-#ifndef PY_SSIZE_T_MAX
-#define PY_SSIZE_T_MAX LONG_MAX
-#endif
-
-/* The translation function for each format character is table driven */
-typedef struct _formatdef {
-	char format;
-	Py_ssize_t size;
-	Py_ssize_t alignment;
-	PyObject* (*unpack)(const char *,
-			    const struct _formatdef *);
-	int (*pack)(char *, PyObject *,
-		    const struct _formatdef *);
-} formatdef;
-
-typedef struct _formatcode {
-	const struct _formatdef *fmtdef;
-	Py_ssize_t offset;
-	Py_ssize_t size;
-} formatcode;
-
-/* Struct object interface */
-
-typedef struct {
-	PyObject_HEAD
-	Py_ssize_t s_size;
-	Py_ssize_t s_len;
-	formatcode *s_codes;
-	PyObject *s_format;
-	PyObject *weakreflist; /* List of weak references */
-} PyStructObject;
-
-
-#define PyStruct_Check(op) PyObject_TypeCheck(op, &PyStructType)
-#define PyStruct_CheckExact(op) (Py_TYPE(op) == &PyStructType)
-
-
-/* Exception */
-
-static PyObject *StructError;
-
-
-/* Define various structs to figure out the alignments of types */
-
-
-typedef struct { char c; short x; } st_short;
-typedef struct { char c; int x; } st_int;
-typedef struct { char c; long x; } st_long;
-typedef struct { char c; float x; } st_float;
-typedef struct { char c; double x; } st_double;
-typedef struct { char c; void *x; } st_void_p;
-
-#define SHORT_ALIGN (sizeof(st_short) - sizeof(short))
-#define INT_ALIGN (sizeof(st_int) - sizeof(int))
-#define LONG_ALIGN (sizeof(st_long) - sizeof(long))
-#define FLOAT_ALIGN (sizeof(st_float) - sizeof(float))
-#define DOUBLE_ALIGN (sizeof(st_double) - sizeof(double))
-#define VOID_P_ALIGN (sizeof(st_void_p) - sizeof(void *))
-
-/* We can't support q and Q in native mode unless the compiler does;
-   in std mode, they're 8 bytes on all platforms. */
-#ifdef HAVE_LONG_LONG
-typedef struct { char c; PY_LONG_LONG x; } s_long_long;
-#define LONG_LONG_ALIGN (sizeof(s_long_long) - sizeof(PY_LONG_LONG))
-#endif
-
-#define BOOL_TYPE bool
-typedef struct { char c; bool x; } s_bool;
-#define BOOL_ALIGN (sizeof(s_bool) - sizeof(BOOL_TYPE))
-
-#define STRINGIFY(x)    #x
-
-#ifdef __powerc
-#pragma options align=reset
-#endif
-
-static char *integer_codes = "bBhHiIlLqQ";
-
-static void s_dealloc(PyStructObject *s);
-static int s_init(PyObject *self, PyObject *args, PyObject *kwds);
-static PyObject *s_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-static PyObject *s_pack(PyObject *self, PyObject *args);
-static PyObject *s_pack_into(PyObject *self, PyObject *args);
-static PyObject *s_unpack(PyObject *self, PyObject *inputstr);
-static PyObject *s_unpack_from(PyObject *self, PyObject *args, PyObject *kwds);
-static PyObject *s_get_format(PyStructObject *self, void *unused);
-static PyObject *s_get_size(PyStructObject *self, void *unused);
-
-PyDoc_STRVAR(s__doc__, "Compiled struct object");
-
-/* List of functions */
-
-PyDoc_STRVAR(s_pack__doc__,
-"S.pack(v1, v2, ...) -> string\n\
-\n\
-Return a string containing values v1, v2, ... packed according to this\n\
-Struct's format. See struct.__doc__ for more on format strings.");
-
-PyDoc_STRVAR(s_pack_into__doc__,
-"S.pack_into(buffer, offset, v1, v2, ...)\n\
-\n\
-Pack the values v1, v2, ... according to this Struct's format, write \n\
-the packed bytes into the writable buffer buf starting at offset.  Note\n\
-that the offset is not an optional argument.  See struct.__doc__ for \n\
-more on format strings.");
-
-PyDoc_STRVAR(s_unpack__doc__,
-"S.unpack(str) -> (v1, v2, ...)\n\
-\n\
-Return tuple containing values unpacked according to this Struct's format.\n\
-Requires len(str) == self.size. See struct.__doc__ for more on format\n\
-strings.");
-
-PyDoc_STRVAR(s_unpack_from__doc__,
-"S.unpack_from(buffer[, offset]) -> (v1, v2, ...)\n\
-\n\
-Return tuple containing values unpacked according to this Struct's format.\n\
-Unlike unpack, unpack_from can unpack values from any object supporting\n\
-the buffer API, not just str. Requires len(buffer[offset:]) >= self.size.\n\
-See struct.__doc__ for more on format strings.");
-
-
-static struct PyMethodDef s_methods[] = {
-	{"pack",	s_pack,		METH_VARARGS, s_pack__doc__},
-	{"pack_into",	s_pack_into,	METH_VARARGS, s_pack_into__doc__},
-	{"unpack",	s_unpack,       METH_O, s_unpack__doc__},
-	{"unpack_from",	(PyCFunction)s_unpack_from, METH_VARARGS|METH_KEYWORDS,
-			s_unpack_from__doc__},
-	{NULL,	 NULL}		/* sentinel */
-};
-
-#define OFF(x) offsetof(PyStructObject, x)
-
-static PyGetSetDef s_getsetlist[] = {
-	{"format", (getter)s_get_format, (setter)NULL, "struct format string", NULL},
-	{"size", (getter)s_get_size, (setter)NULL, "struct size in bytes", NULL},
-	{NULL} /* sentinel */
-};
-
-static
-PyTypeObject PyStructType = {
-	PyVarObject_HEAD_INIT(NULL, 0)
-	"Struct",
-	sizeof(PyStructObject),
-	0,
-	(destructor)s_dealloc,	/* tp_dealloc */
-	0,					/* tp_print */
-	0,					/* tp_getattr */
-	0,					/* tp_setattr */
-	0,					/* tp_compare */
-	0,					/* tp_repr */
-	0,					/* tp_as_number */
-	0,					/* tp_as_sequence */
-	0,					/* tp_as_mapping */
-	0,					/* tp_hash */
-	0,					/* tp_call */
-	0,					/* tp_str */
-	PyObject_GenericGetAttr,	/* tp_getattro */
-	PyObject_GenericSetAttr,	/* tp_setattro */
-	0,					/* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_WEAKREFS,/* tp_flags */
-	s__doc__,			/* tp_doc */
-	0,					/* tp_traverse */
-	0,					/* tp_clear */
-	0,					/* tp_richcompare */
-	offsetof(PyStructObject, weakreflist),	/* tp_weaklistoffset */
-	0,					/* tp_iter */
-	0,					/* tp_iternext */
-	s_methods,			/* tp_methods */
-	NULL,				/* tp_members */
-	s_getsetlist,		/* tp_getset */
-	0,					/* tp_base */
-	0,					/* tp_dict */
-	0,					/* tp_descr_get */
-	0,					/* tp_descr_set */
-	0,					/* tp_dictoffset */
-	s_init,				/* tp_init */
-	PyType_GenericAlloc,/* tp_alloc */
-	s_new,				/* tp_new */
-	PyObject_Del,		/* tp_free */
-};
-
-/* Helper to get a PyLongObject by hook or by crook.  Caller should decref. */
-
-static PyObject *
-get_pylong(PyObject *v)
-{
-        PyNumberMethods *m;
-
-	assert(v != NULL);
-	if (PyInt_Check(v))
-		return PyLong_FromLong(PyInt_AS_LONG(v));
-	if (PyLong_Check(v)) {
-		Py_INCREF(v);
-		return v;
-	}
-
-        m = Py_TYPE(v)->tp_as_number;
-        if (m != NULL && m->nb_long != NULL) {
-                v = m->nb_long(v);
-                if (v == NULL)
-                        return NULL;
-                if (PyLong_Check(v))
-                        return v;
-                Py_DECREF(v);
-        }
-
-	PyErr_SetString(StructError,
-			"cannot convert argument to long");
-	return NULL;
-}
-
-/* Helper to convert a Python object to a C long.  Sets an exception
-   (struct.error for an inconvertible type, OverflowError for
-   out-of-range values) and returns -1 on error. */
-
-static int
-get_long(PyObject *v, long *p)
-{
-	long x;
-
-	v = get_pylong(v);
-	if (v == NULL)
-		return -1;
-	assert(PyLong_Check(v));
-	x = PyLong_AsLong(v);
-	Py_DECREF(v);
-	if (x == (long)-1 && PyErr_Occurred())
-		return -1;
-	*p = x;
-	return 0;
-}
-
-/* Same, but handling unsigned long */
-
-static int
-get_ulong(PyObject *v, unsigned long *p)
-{
-	unsigned long x;
-
-	v = get_pylong(v);
-	if (v == NULL)
-		return -1;
-	assert(PyLong_Check(v));
-	x = PyLong_AsUnsignedLong(v);
-	Py_DECREF(v);
-	if (x == (unsigned long)-1 && PyErr_Occurred())
-		return -1;
-	*p = x;
-	return 0;
-}
-
-#ifdef HAVE_LONG_LONG
-
-/* Same, but handling native long long. */
-
-static int
-get_longlong(PyObject *v, PY_LONG_LONG *p)
-{
-	PY_LONG_LONG x;
-
-	v = get_pylong(v);
-	if (v == NULL)
-		return -1;
-	assert(PyLong_Check(v));
-	x = PyLong_AsLongLong(v);
-	Py_DECREF(v);
-	if (x == (PY_LONG_LONG)-1 && PyErr_Occurred())
-		return -1;
-	*p = x;
-	return 0;
-}
-
-/* Same, but handling native unsigned long long. */
-
-static int
-get_ulonglong(PyObject *v, unsigned PY_LONG_LONG *p)
-{
-	unsigned PY_LONG_LONG x;
-
-	v = get_pylong(v);
-	if (v == NULL)
-		return -1;
-	assert(PyLong_Check(v));
-	x = PyLong_AsUnsignedLongLong(v);
-	Py_DECREF(v);
-	if (x == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())
-		return -1;
-	*p = x;
-	return 0;
-}
-
-#endif
-
-#if (SIZEOF_LONG > SIZEOF_INT)
-
-/* Helper to format the range error exceptions */
-static int
-_range_error(const formatdef *f, int is_unsigned)
-{
-	/* ulargest is the largest unsigned value with f->size bytes.
-	 * Note that the simpler:
-	 *     ((size_t)1 << (f->size * 8)) - 1
-	 * doesn't work when f->size == sizeof(size_t) because C doesn't
-	 * define what happens when a left shift count is >= the number of
-	 * bits in the integer being shifted; e.g., on some boxes it doesn't
-	 * shift at all when they're equal.
-	 */
-	const size_t ulargest = (size_t)-1 >> ((SIZEOF_SIZE_T - f->size)*8);
-	assert(f->size >= 1 && f->size <= SIZEOF_SIZE_T);
-	if (is_unsigned)
-		PyErr_Format(StructError,
-			"'%c' format requires 0 <= number <= %zu",
-			f->format,
-			ulargest);
-	else {
-		const Py_ssize_t largest = (Py_ssize_t)(ulargest >> 1);
-		PyErr_Format(StructError,
-			"'%c' format requires %zd <= number <= %zd",
-			f->format,
-			~ largest,
-			largest);
-	}
-	return -1;
-}
-
-#endif
-
-
-/* A large number of small routines follow, with names of the form
-
-   [bln][up]_TYPE
-
-   [bln] distiguishes among big-endian, little-endian and native.
-   [pu] distiguishes between pack (to struct) and unpack (from struct).
-   TYPE is one of char, byte, ubyte, etc.
-*/
-
-/* Native mode routines. ****************************************************/
-/* NOTE:
-   In all n[up]_<type> routines handling types larger than 1 byte, there is
-   *no* guarantee that the p pointer is properly aligned for each type,
-   therefore memcpy is called.  An intermediate variable is used to
-   compensate for big-endian architectures.
-   Normally both the intermediate variable and the memcpy call will be
-   skipped by C optimisation in little-endian architectures (gcc >= 2.91
-   does this). */
-
-static PyObject *
-nu_char(const char *p, const formatdef *f)
-{
-	return PyString_FromStringAndSize(p, 1);
-}
-
-static PyObject *
-nu_byte(const char *p, const formatdef *f)
-{
-	return PyInt_FromLong((long) *(signed char *)p);
-}
-
-static PyObject *
-nu_ubyte(const char *p, const formatdef *f)
-{
-	return PyInt_FromLong((long) *(unsigned char *)p);
-}
-
-static PyObject *
-nu_short(const char *p, const formatdef *f)
-{
-	short x;
-	memcpy((char *)&x, p, sizeof x);
-	return PyInt_FromLong((long)x);
-}
-
-static PyObject *
-nu_ushort(const char *p, const formatdef *f)
-{
-	unsigned short x;
-	memcpy((char *)&x, p, sizeof x);
-	return PyInt_FromLong((long)x);
-}
-
-static PyObject *
-nu_int(const char *p, const formatdef *f)
-{
-	int x;
-	memcpy((char *)&x, p, sizeof x);
-	return PyInt_FromLong((long)x);
-}
-
-static PyObject *
-nu_uint(const char *p, const formatdef *f)
-{
-	unsigned int x;
-	memcpy((char *)&x, p, sizeof x);
-#if (SIZEOF_LONG > SIZEOF_INT)
-	return PyInt_FromLong((long)x);
-#else
-	if (x <= ((unsigned int)LONG_MAX))
-		return PyInt_FromLong((long)x);
-	return PyLong_FromUnsignedLong((unsigned long)x);
-#endif
-}
-
-static PyObject *
-nu_long(const char *p, const formatdef *f)
-{
-	long x;
-	memcpy((char *)&x, p, sizeof x);
-	return PyInt_FromLong(x);
-}
-
-static PyObject *
-nu_ulong(const char *p, const formatdef *f)
-{
-	unsigned long x;
-	memcpy((char *)&x, p, sizeof x);
-	if (x <= LONG_MAX)
-		return PyInt_FromLong((long)x);
-	return PyLong_FromUnsignedLong(x);
-}
-
-/* Native mode doesn't support q or Q unless the platform C supports
-   long long (or, on Windows, __int64). */
-
-#ifdef HAVE_LONG_LONG
-
-static PyObject *
-nu_longlong(const char *p, const formatdef *f)
-{
-	PY_LONG_LONG x;
-	memcpy((char *)&x, p, sizeof x);
-	if (x >= LONG_MIN && x <= LONG_MAX)
-		return PyInt_FromLong(Py_SAFE_DOWNCAST(x, PY_LONG_LONG, long));
-	return PyLong_FromLongLong(x);
-}
-
-static PyObject *
-nu_ulonglong(const char *p, const formatdef *f)
-{
-	unsigned PY_LONG_LONG x;
-	memcpy((char *)&x, p, sizeof x);
-	if (x <= LONG_MAX)
-		return PyInt_FromLong(Py_SAFE_DOWNCAST(x, unsigned PY_LONG_LONG, long));
-	return PyLong_FromUnsignedLongLong(x);
-}
-
-#endif
-
-static PyObject *
-nu_bool(const char *p, const formatdef *f)
-{
-	BOOL_TYPE x;
-	memcpy((char *)&x, p, sizeof x);
-	return PyBool_FromLong(x != 0);
-}
-
-
-static PyObject *
-nu_float(const char *p, const formatdef *f)
-{
-	float x;
-	memcpy((char *)&x, p, sizeof x);
-	return PyFloat_FromDouble((double)x);
-}
-
-static PyObject *
-nu_double(const char *p, const formatdef *f)
-{
-	double x;
-	memcpy((char *)&x, p, sizeof x);
-	return PyFloat_FromDouble(x);
-}
-
-static PyObject *
-nu_complex_float(const char *p, const formatdef *f)
-{
-	float re, im;
-	memcpy((char *)&re, p, sizeof re);
-	memcpy((char *)&im, p+sizeof re, sizeof im);
-	return PyComplex_FromDoubles((double)re, (double) im);
-}
-
-static PyObject *
-nu_complex_double(const char *p, const formatdef *f)
-{
-	double re, im;
-	memcpy((char *)&re, p, sizeof re);
-	memcpy((char *)&im, p+sizeof re, sizeof im);
-	return PyComplex_FromDoubles(re, im);
-}
-
-static PyObject *
-nu_void_p(const char *p, const formatdef *f)
-{
-	void *x;
-	memcpy((char *)&x, p, sizeof x);
-	return PyLong_FromVoidPtr(x);
-}
-
-static int
-np_byte(char *p, PyObject *v, const formatdef *f)
-{
-	long x;
-	if (get_long(v, &x) < 0)
-		return -1;
-	if (x < -128 || x > 127){
-		PyErr_SetString(StructError,
-				"byte format requires -128 <= number <= 127");
-		return -1;
-	}
-	*p = (char)x;
-	return 0;
-}
-
-static int
-np_ubyte(char *p, PyObject *v, const formatdef *f)
-{
-	long x;
-	if (get_long(v, &x) < 0)
-		return -1;
-	if (x < 0 || x > 255){
-		PyErr_SetString(StructError,
-				"ubyte format requires 0 <= number <= 255");
-		return -1;
-	}
-	*p = (char)x;
-	return 0;
-}
-
-static int
-np_char(char *p, PyObject *v, const formatdef *f)
-{
-	if (!PyString_Check(v) || PyString_Size(v) != 1) {
-		PyErr_SetString(StructError,
-				"char format require string of length 1");
-		return -1;
-	}
-	*p = *PyString_AsString(v);
-	return 0;
-}
-
-static int
-np_short(char *p, PyObject *v, const formatdef *f)
-{
-	long x;
-	short y;
-	if (get_long(v, &x) < 0)
-		return -1;
-	if (x < SHRT_MIN || x > SHRT_MAX){
-		PyErr_SetString(StructError,
-				"short format requires " STRINGIFY(SHRT_MIN)
-				" <= number <= " STRINGIFY(SHRT_MAX));
-		return -1;
-	}
-	y = (short)x;
-	memcpy(p, (char *)&y, sizeof y);
-	return 0;
-}
-
-static int
-np_ushort(char *p, PyObject *v, const formatdef *f)
-{
-	long x;
-	unsigned short y;
-	if (get_long(v, &x) < 0)
-		return -1;
-	if (x < 0 || x > USHRT_MAX){
-		PyErr_SetString(StructError,
-				"ushort format requires 0 <= number <= " STRINGIFY(USHRT_MAX));
-		return -1;
-	}
-	y = (unsigned short)x;
-	memcpy(p, (char *)&y, sizeof y);
-	return 0;
-}
-
-static int
-np_int(char *p, PyObject *v, const formatdef *f)
-{
-	long x;
-	int y;
-	if (get_long(v, &x) < 0)
-		return -1;
-#if (SIZEOF_LONG > SIZEOF_INT)
-	if ((x < ((long)INT_MIN)) || (x > ((long)INT_MAX)))
-		return _range_error(f, 0);
-#endif
-	y = (int)x;
-	memcpy(p, (char *)&y, sizeof y);
-	return 0;
-}
-
-static int
-np_uint(char *p, PyObject *v, const formatdef *f)
-{
-	unsigned long x;
-	unsigned int y;
-	if (get_ulong(v, &x) < 0)
-		return -1;
-	y = (unsigned int)x;
-#if (SIZEOF_LONG > SIZEOF_INT)
-	if (x > ((unsigned long)UINT_MAX))
-		return _range_error(f, 1);
-#endif
-	memcpy(p, (char *)&y, sizeof y);
-	return 0;
-}
-
-static int
-np_long(char *p, PyObject *v, const formatdef *f)
-{
-	long x;
-	if (get_long(v, &x) < 0)
-		return -1;
-	memcpy(p, (char *)&x, sizeof x);
-	return 0;
-}
-
-static int
-np_ulong(char *p, PyObject *v, const formatdef *f)
-{
-	unsigned long x;
-	if (get_ulong(v, &x) < 0)
-		return -1;
-	memcpy(p, (char *)&x, sizeof x);
-	return 0;
-}
-
-#ifdef HAVE_LONG_LONG
-
-static int
-np_longlong(char *p, PyObject *v, const formatdef *f)
-{
-	PY_LONG_LONG x;
-	if (get_longlong(v, &x) < 0)
-		return -1;
-	memcpy(p, (char *)&x, sizeof x);
-	return 0;
-}
-
-static int
-np_ulonglong(char *p, PyObject *v, const formatdef *f)
-{
-	unsigned PY_LONG_LONG x;
-	if (get_ulonglong(v, &x) < 0)
-		return -1;
-	memcpy(p, (char *)&x, sizeof x);
-	return 0;
-}
-#endif
-
-
-static int
-np_bool(char *p, PyObject *v, const formatdef *f)
-{
-	BOOL_TYPE y; 
-	y = PyObject_IsTrue(v) != 0;
-	memcpy(p, (char *)&y, sizeof y);
-	return 0;
-}
-
-static int
-np_float(char *p, PyObject *v, const formatdef *f)
-{
-	float x = (float)PyFloat_AsDouble(v);
-	if (x == -1 && PyErr_Occurred()) {
-		PyErr_SetString(StructError,
-				"required argument is not a float");
-		return -1;
-	}
-	memcpy(p, (char *)&x, sizeof x);
-	return 0;
-}
-
-static int
-np_double(char *p, PyObject *v, const formatdef *f)
-{
-	double x = PyFloat_AsDouble(v);
-	if (x == -1 && PyErr_Occurred()) {
-		PyErr_SetString(StructError,
-				"required argument is not a float");
-		return -1;
-	}
-	memcpy(p, (char *)&x, sizeof(double));
-	return 0;
-}
-
-static int
-np_complex_float(char *p, PyObject *v, const formatdef *f)
-{
-        if (PyArray_IsZeroDim(v)) {
-		PyObject *v_cast = PyArray_Cast(
-				reinterpret_cast<PyArrayObject *>(v),
-				NPY_CFLOAT);
-		if (!v_cast)
-			return -1;
-		memcpy(p, PyArray_DATA(v_cast), PyArray_NBYTES(v_cast));
-		Py_DECREF(v_cast);
-	}
-	else {
-		float re = 0.0f;
-		float im = 0.0f;
-		Py_complex cplx;
-#if (PY_VERSION_HEX < 0x02060000)
-			if (PyComplex_Check(v))
-				cplx = PyComplex_AsCComplex(v);
-			else if (PyObject_HasAttrString(v, "__complex__"))
-			{
-				PyObject *v2 = PyObject_CallMethod(v, "__complex__", "");
-				cplx = PyComplex_AsCComplex(v2);
-				Py_DECREF(v2);
-			}
-			else
-				cplx = PyComplex_AsCComplex(v);
-#else
-			cplx = PyComplex_AsCComplex(v);
-#endif
-		if (PyErr_Occurred()) {
-			PyErr_SetString(StructError,
-					"required argument is not a complex");
-			return -1;
-		}
-
-		re = (float)cplx.real;
-		im = (float)cplx.imag;
-		memcpy(p, (char *)&re, sizeof re);
-		memcpy(p+sizeof re, (char *)&im, sizeof im);
-	}
-	return 0;
-}
-
-static int
-np_complex_double(char *p, PyObject *v, const formatdef *f)
-{
-        if (PyArray_IsZeroDim(v)) {
-		PyObject *v_cast = PyArray_Cast(
-				reinterpret_cast<PyArrayObject *>(v),
-				NPY_CDOUBLE);
-		if (!v_cast)
-			return -1;
-		memcpy(p, PyArray_DATA(v_cast), PyArray_NBYTES(v_cast));
-		Py_DECREF(v_cast);
-	}
-	else {
-		double re = 0.0;
-		double im = 0.0;
-		Py_complex cplx;
-#if (PY_VERSION_HEX < 0x02060000)
-			if (PyComplex_Check(v))
-				cplx = PyComplex_AsCComplex(v);
-			else if (PyObject_HasAttrString(v, "__complex__"))
-			{
-				PyObject *v2 = PyObject_CallMethod(v, "__complex__", "");
-				cplx = PyComplex_AsCComplex(v2);
-				Py_DECREF(v2);
-			}
-			else
-				cplx = PyComplex_AsCComplex(v);
-#else
-			cplx = PyComplex_AsCComplex(v);
-#endif
-		if (PyErr_Occurred()) {
-			PyErr_SetString(StructError,
-					"required argument is not a complex");
-			return -1;
-		}
-		re = cplx.real;
-		im = cplx.imag;
-		memcpy(p, (char *)&re, sizeof re);
-		memcpy(p+sizeof re, (char *)&im, sizeof im);
-	}
-	return 0;
-}
-
-static int
-np_void_p(char *p, PyObject *v, const formatdef *f)
-{
-	void *x;
-
-	v = get_pylong(v);
-	if (v == NULL)
-		return -1;
-	assert(PyLong_Check(v));
-	x = PyLong_AsVoidPtr(v);
-	Py_DECREF(v);
-	if (x == NULL && PyErr_Occurred())
-		return -1;
-	memcpy(p, (char *)&x, sizeof x);
-	return 0;
-}
-
-static formatdef native_table[] = {
-	{'x',	sizeof(char),	0,		NULL},
-	{'b',	sizeof(char),	0,		nu_byte,	np_byte},
-	{'B',	sizeof(char),	0,		nu_ubyte,	np_ubyte},
-	{'c',	sizeof(char),	0,		nu_char,	np_char},
-	{'s',	sizeof(char),	0,		NULL},
-	{'p',	sizeof(char),	0,		NULL},
-	{'h',	sizeof(short),	SHORT_ALIGN,	nu_short,	np_short},
-	{'H',	sizeof(short),	SHORT_ALIGN,	nu_ushort,	np_ushort},
-	{'i',	sizeof(int),	INT_ALIGN,	nu_int,		np_int},
-	{'I',	sizeof(int),	INT_ALIGN,	nu_uint,	np_uint},
-	{'l',	sizeof(long),	LONG_ALIGN,	nu_long,	np_long},
-	{'L',	sizeof(long),	LONG_ALIGN,	nu_ulong,	np_ulong},
-#ifdef HAVE_LONG_LONG
-	{'q',	sizeof(PY_LONG_LONG), LONG_LONG_ALIGN, nu_longlong, np_longlong},
-	{'Q',	sizeof(PY_LONG_LONG), LONG_LONG_ALIGN, nu_ulonglong,np_ulonglong},
-#endif
-	{'?',	sizeof(BOOL_TYPE),	BOOL_ALIGN,	nu_bool,	np_bool},
-	{'f',	sizeof(float),	FLOAT_ALIGN,	nu_float,	np_float},
-	{'d',	sizeof(double),	DOUBLE_ALIGN,	nu_double,	np_double},
-	{'F',	2*sizeof(float),	FLOAT_ALIGN,	nu_complex_float,	np_complex_float},
-	{'D',	2*sizeof(double),	DOUBLE_ALIGN,	nu_complex_double,	np_complex_double},
-	{'P',	sizeof(void *),	VOID_P_ALIGN,	nu_void_p,	np_void_p},
-	{0}
-};
-
-/* Get the table entry for a format code */
-
-static const formatdef *
-getentry(int c, const formatdef *f)
-{
-	for (; f->format != '\0'; f++) {
-		if (f->format == c) {
-			return f;
-		}
-	}
-	PyErr_SetString(StructError, "bad char in struct format");
-	return NULL;
-}
-
-
-/* Align a size according to a format code */
-
-static Py_ssize_t
-align(Py_ssize_t size, char c, const formatdef *e)
-{
-	if (e->format == c) {
-		if (e->alignment) {
-			size = ((size + e->alignment - 1)
-				/ e->alignment)
-				* e->alignment;
-		}
-	}
-	return size;
-}
-
-
-/* calculate the size of a format string */
-
-static int
-prepare_s(PyStructObject *self)
-{
-	const formatdef *f;
-	const formatdef *e;
-	formatcode *codes;
-
-	const char *s;
-	const char *fmt;
-	char c;
-	Py_ssize_t size, len, num, itemsize, x;
-
-	fmt = PyString_AS_STRING(self->s_format);
-
-	f = native_table;
-
-	s = fmt;
-	size = 0;
-	len = 0;
-	while ((c = *s++) != '\0') {
-		if (isspace(Py_CHARMASK(c)))
-			continue;
-		if ('0' <= c && c <= '9') {
-			num = c - '0';
-			while ('0' <= (c = *s++) && c <= '9') {
-				x = num*10 + (c - '0');
-				if (x/10 != num) {
-					PyErr_SetString(
-						StructError,
-						"overflow in item count");
-					return -1;
-				}
-				num = x;
-			}
-			if (c == '\0')
-				break;
-		}
-		else
-			num = 1;
-
-		e = getentry(c, f);
-		if (e == NULL)
-			return -1;
-
-		switch (c) {
-			case 's': /* fall through */
-			case 'p': len++; break;
-			case 'x': break;
-			default: len += num; break;
-		}
-
-		itemsize = e->size;
-		size = align(size, c, e);
-		x = num * itemsize;
-		size += x;
-		if (x/itemsize != num || size < 0) {
-			PyErr_SetString(StructError,
-					"total struct size too long");
-			return -1;
-		}
-	}
-
-	/* check for overflow */
-	if ((len + 1) > (PY_SSIZE_T_MAX / sizeof(formatcode))) {
-		PyErr_NoMemory();
-		return -1;
-	}
-
-	self->s_size = size;
-	self->s_len = len;
-	codes = (formatcode *) PyMem_MALLOC((len + 1) * sizeof(formatcode));
-	if (codes == NULL) {
-		PyErr_NoMemory();
-		return -1;
-	}
-	self->s_codes = codes;
-
-	s = fmt;
-	size = 0;
-	while ((c = *s++) != '\0') {
-		if (isspace(Py_CHARMASK(c)))
-			continue;
-		if ('0' <= c && c <= '9') {
-			num = c - '0';
-			while ('0' <= (c = *s++) && c <= '9')
-				num = num*10 + (c - '0');
-			if (c == '\0')
-				break;
-		}
-		else
-			num = 1;
-
-		e = getentry(c, f);
-
-		size = align(size, c, e);
-		if (c == 's' || c == 'p') {
-			codes->offset = size;
-			codes->size = num;
-			codes->fmtdef = e;
-			codes++;
-			size += num;
-		} else if (c == 'x') {
-			size += num;
-		} else {
-			while (--num >= 0) {
-				codes->offset = size;
-				codes->size = e->size;
-				codes->fmtdef = e;
-				codes++;
-				size += e->size;
-			}
-		}
-	}
-	codes->fmtdef = NULL;
-	codes->offset = size;
-	codes->size = 0;
-
-	return 0;
-}
-
-static PyObject *
-s_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
-	PyObject *self;
-
-	assert(type != NULL && type->tp_alloc != NULL);
-
-	self = type->tp_alloc(type, 0);
-	if (self != NULL) {
-		PyStructObject *s = (PyStructObject*)self;
-		Py_INCREF(Py_None);
-		s->s_format = Py_None;
-		s->s_codes = NULL;
-		s->s_size = -1;
-		s->s_len = -1;
-	}
-	return self;
-}
-
-static int
-s_init(PyObject *self, PyObject *args, PyObject *kwds)
-{
-	PyStructObject *soself = (PyStructObject *)self;
-	PyObject *o_format = NULL;
-	int ret = 0;
-	static char *kwlist[] = {"format", 0};
-
-	assert(PyStruct_Check(self));
-
-	if (!PyArg_ParseTupleAndKeywords(args, kwds, "S:Struct", kwlist,
-					 &o_format))
-		return -1;
-
-	Py_INCREF(o_format);
-	Py_CLEAR(soself->s_format);
-	soself->s_format = o_format;
-
-	ret = prepare_s(soself);
-	return ret;
-}
-
-static void
-s_dealloc(PyStructObject *s)
-{
-	if (s->weakreflist != NULL)
-		PyObject_ClearWeakRefs((PyObject *)s);
-	if (s->s_codes != NULL) {
-		PyMem_FREE(s->s_codes);
-	}
-	Py_XDECREF(s->s_format);
-	Py_TYPE(s)->tp_free((PyObject *)s);
-}
-
-static PyObject *
-s_unpack_internal(PyStructObject *soself, char *startfrom) {
-	formatcode *code;
-	Py_ssize_t i = 0;
-	PyObject *result = PyTuple_New(soself->s_len);
-	if (result == NULL)
-		return NULL;
-
-	for (code = soself->s_codes; code->fmtdef != NULL; code++) {
-		PyObject *v;
-		const formatdef *e = code->fmtdef;
-		const char *res = startfrom + code->offset;
-		if (e->format == 's') {
-			v = PyString_FromStringAndSize(res, code->size);
-		} else if (e->format == 'p') {
-			Py_ssize_t n = *(unsigned char*)res;
-			if (n >= code->size)
-				n = code->size - 1;
-			v = PyString_FromStringAndSize(res + 1, n);
-		} else {
-			v = e->unpack(res, e);
-		}
-		if (v == NULL)
-			goto fail;
-		PyTuple_SET_ITEM(result, i++, v);
-	}
-
-	return result;
-fail:
-	Py_DECREF(result);
-	return NULL;
-}
-
-
-static PyObject *
-s_unpack(PyObject *self, PyObject *inputstr)
-{
-	char *start;
-	Py_ssize_t len;
-	PyObject *args=NULL, *result;
-	PyStructObject *soself = (PyStructObject *)self;
-	assert(PyStruct_Check(self));
-	assert(soself->s_codes != NULL);
-	if (inputstr == NULL)
-		goto fail;
-	if (PyString_Check(inputstr) &&
-		PyString_GET_SIZE(inputstr) == soself->s_size) {
-			return s_unpack_internal(soself, PyString_AS_STRING(inputstr));
-	}
-	args = PyTuple_Pack(1, inputstr);
-	if (args == NULL)
-		return NULL;
-	if (!PyArg_ParseTuple(args, "s#:unpack", &start, &len))
-		goto fail;
-	if (soself->s_size != len)
-		goto fail;
-	result = s_unpack_internal(soself, start);
-	Py_DECREF(args);
-	return result;
-
-fail:
-	Py_XDECREF(args);
-	PyErr_Format(StructError,
-		"unpack requires a string argument of length %zd",
-		soself->s_size);
-	return NULL;
-}
-
-static PyObject *
-s_unpack_from(PyObject *self, PyObject *args, PyObject *kwds)
-{
-	static char *kwlist[] = {"buffer", "offset", 0};
-#if (PY_VERSION_HEX < 0x02050000)
-	static char *fmt = "z#|i:unpack_from";
-#else
-	static char *fmt = "z#|n:unpack_from";
-#endif
-	Py_ssize_t buffer_len = 0, offset = 0;
-	char *buffer = NULL;
-	PyStructObject *soself = (PyStructObject *)self;
-	assert(PyStruct_Check(self));
-	assert(soself->s_codes != NULL);
-
-	if (!PyArg_ParseTupleAndKeywords(args, kwds, fmt, kwlist,
-					 &buffer, &buffer_len, &offset))
-		return NULL;
-
-	if (buffer == NULL) {
-		PyErr_Format(StructError,
-			"unpack_from requires a buffer argument");
-		return NULL;
-	}
-
-	if (offset < 0)
-		offset += buffer_len;
-
-	if (offset < 0 || (buffer_len - offset) < soself->s_size) {
-		PyErr_Format(StructError,
-			"unpack_from requires a buffer of at least %zd bytes",
-			soself->s_size);
-		return NULL;
-	}
-	return s_unpack_internal(soself, buffer + offset);
-}
-
-
-/*
- * Guts of the pack function.
- *
- * Takes a struct object, a tuple of arguments, and offset in that tuple of
- * argument for where to start processing the arguments for packing, and a
- * character buffer for writing the packed string.  The caller must insure
- * that the buffer may contain the required length for packing the arguments.
- * 0 is returned on success, 1 is returned if there is an error.
- *
- */
-static int
-s_pack_internal(PyStructObject *soself, PyObject *args, int offset, char* buf)
-{
-	formatcode *code;
-	/* XXX(nnorwitz): why does i need to be a local?  can we use
-	   the offset parameter or do we need the wider width? */
-	Py_ssize_t i;
-
-	memset(buf, '\0', soself->s_size);
-	i = offset;
-	for (code = soself->s_codes; code->fmtdef != NULL; code++) {
-		Py_ssize_t n;
-		PyObject *v = PyTuple_GET_ITEM(args, i++);
-		const formatdef *e = code->fmtdef;
-		char *res = buf + code->offset;
-		if (e->format == 's') {
-			if (!PyString_Check(v)) {
-				if (!PyObject_CheckReadBuffer(v))
-				{
-					PyErr_SetString(StructError,
-							"argument for 's' must "
-							"be a string or a buffer");
-					return -1;
-				}
-				else
-				{
-					const void *buf;
-					Py_ssize_t len;
-					if (PyObject_AsReadBuffer(v, &buf, &len))
-						return -1;
-
-					if (len > code->size)
-						len = code->size;
-					if (len > 0)
-						memcpy(res, buf, len);
-				}
-			}
-			else
-			{
-				n = PyString_GET_SIZE(v);
-				if (n > code->size)
-					n = code->size;
-				if (n > 0)
-					memcpy(res, PyString_AS_STRING(v), n);
-			}
-		} else if (e->format == 'p') {
-			if (!PyString_Check(v)) {
-				PyErr_SetString(StructError,
-						"argument for 'p' must "
-						"be a string");
-				return -1;
-			}
-			n = PyString_GET_SIZE(v);
-			if (n > (code->size - 1))
-				n = code->size - 1;
-			if (n > 0)
-				memcpy(res + 1, PyString_AS_STRING(v), n);
-			if (n > 255)
-				n = 255;
-			*res = Py_SAFE_DOWNCAST(n, Py_ssize_t, unsigned char);
-		} else if (e->pack(res, v, e) < 0) {
-			if (strchr(integer_codes, e->format) != NULL &&
-			    PyErr_ExceptionMatches(PyExc_OverflowError))
-				PyErr_Format(StructError,
-					     "integer out of range for "
-					     "'%c' format code",
-					     e->format);
-			return -1;
-		}
-	}
-
-	/* Success */
-	return 0;
-}
-
-
-static PyObject *
-s_pack(PyObject *self, PyObject *args)
-{
-	PyStructObject *soself;
-	PyObject *result;
-
-	/* Validate arguments. */
-	soself = (PyStructObject *)self;
-	assert(PyStruct_Check(self));
-	assert(soself->s_codes != NULL);
-	if (PyTuple_GET_SIZE(args) != soself->s_len)
-	{
-		PyErr_Format(StructError,
-			"pack requires exactly %zd arguments", soself->s_len);
-		return NULL;
-	}
-
-	/* Allocate a new string */
-	result = PyString_FromStringAndSize((char *)NULL, soself->s_size);
-	if (result == NULL)
-		return NULL;
-
-	/* Call the guts */
-	if ( s_pack_internal(soself, args, 0, PyString_AS_STRING(result)) != 0 ) {
-		Py_DECREF(result);
-		return NULL;
-	}
-
-	return result;
-}
-
-
-static PyObject *
-s_pack_into(PyObject *self, PyObject *args)
-{
-	PyStructObject *soself;
-	char *buffer;
-	Py_ssize_t buffer_len, offset;
-
-	/* Validate arguments.  +1 is for the first arg as buffer. */
-	soself = (PyStructObject *)self;
-	assert(PyStruct_Check(self));
-	assert(soself->s_codes != NULL);
-	if (PyTuple_GET_SIZE(args) != (soself->s_len + 2))
-	{
-		PyErr_Format(StructError,
-			     "pack_into requires exactly %zd arguments",
-			     (soself->s_len + 2));
-		return NULL;
-	}
-
-	/* Extract a writable memory buffer from the first argument */
-	if ( PyObject_AsWriteBuffer(PyTuple_GET_ITEM(args, 0),
-								(void**)&buffer, &buffer_len) == -1 ) {
-		return NULL;
-	}
-	assert( buffer_len >= 0 );
-
-	/* Extract the offset from the first argument */
-	offset = PyInt_AsSsize_t(PyTuple_GET_ITEM(args, 1));
-	if (offset == -1 && PyErr_Occurred())
-		return NULL;
-
-	/* Support negative offsets. */
-	if (offset < 0)
-		offset += buffer_len;
-
-	/* Check boundaries */
-	if (offset < 0 || (buffer_len - offset) < soself->s_size) {
-		PyErr_Format(StructError,
-			     "pack_into requires a buffer of at least %zd bytes",
-			     soself->s_size);
-		return NULL;
-	}
-
-	/* Call the guts */
-	if ( s_pack_internal(soself, args, 2, buffer + offset) != 0 ) {
-		return NULL;
-	}
-
-	Py_RETURN_NONE;
-}
-
-static PyObject *
-s_get_format(PyStructObject *self, void *unused)
-{
-	Py_INCREF(self->s_format);
-	return self->s_format;
-}
-
-static PyObject *
-s_get_size(PyStructObject *self, void *unused)
-{
-    return PyInt_FromSsize_t(self->s_size);
-}
-
-/* ---- Standalone functions  ---- */
-
-#define MAXCACHE 100
-static PyObject *cache = NULL;
-
-static PyObject *
-cache_struct(PyObject *fmt)
-{
-	PyObject * s_object;
-
-	if (cache == NULL) {
-		cache = PyDict_New();
-		if (cache == NULL)
-			return NULL;
-	}
-
-	s_object = PyDict_GetItem(cache, fmt);
-	if (s_object != NULL) {
-		Py_INCREF(s_object);
-		return s_object;
-	}
-
-	s_object = PyObject_CallFunctionObjArgs((PyObject *)(&PyStructType), fmt, NULL);
-	if (s_object != NULL) {
-		if (PyDict_Size(cache) >= MAXCACHE)
-			PyDict_Clear(cache);
-		/* Attempt to cache the result */
-		if (PyDict_SetItem(cache, fmt, s_object) == -1)
-			PyErr_Clear();
-	}
-	return s_object;
-}
-
-PyDoc_STRVAR(clearcache_doc,
-"Clear the internal cache.");
-
-static PyObject *
-clearcache(PyObject *self)
-{
-	Py_CLEAR(cache);
-	Py_RETURN_NONE;
-}
-
-PyDoc_STRVAR(calcsize_doc,
-"Return size of C struct described by format string fmt.");
-
-static PyObject *
-calcsize(PyObject *self, PyObject *fmt)
-{
-	Py_ssize_t n;
-	PyObject *s_object = cache_struct(fmt);
-	if (s_object == NULL)
-		return NULL;
-	n = ((PyStructObject *)s_object)->s_size;
-	Py_DECREF(s_object);
-    	return PyInt_FromSsize_t(n);
-}
-
-PyDoc_STRVAR(pack_doc,
-"Return string containing values v1, v2, ... packed according to fmt.");
-
-static PyObject *
-pack(PyObject *self, PyObject *args)
-{
-	PyObject *s_object, *fmt, *newargs, *result;
-	Py_ssize_t n = PyTuple_GET_SIZE(args);
-
-	if (n == 0) {
-		PyErr_SetString(PyExc_TypeError, "missing format argument");
-		return NULL;
-	}
-	fmt = PyTuple_GET_ITEM(args, 0);
-	newargs = PyTuple_GetSlice(args, 1, n);
-	if (newargs == NULL)
-		return NULL;
-
-	s_object = cache_struct(fmt);
-	if (s_object == NULL) {
-		Py_DECREF(newargs);
-		return NULL;
-	}
-    	result = s_pack(s_object, newargs);
-	Py_DECREF(newargs);
-	Py_DECREF(s_object);
-	return result;
-}
-
-PyDoc_STRVAR(pack_into_doc,
-"Pack the values v1, v2, ... according to fmt.\n\
-Write the packed bytes into the writable buffer buf starting at offset.");
-
-static PyObject *
-pack_into(PyObject *self, PyObject *args)
-{
-	PyObject *s_object, *fmt, *newargs, *result;
-	Py_ssize_t n = PyTuple_GET_SIZE(args);
-
-	if (n == 0) {
-		PyErr_SetString(PyExc_TypeError, "missing format argument");
-		return NULL;
-	}
-	fmt = PyTuple_GET_ITEM(args, 0);
-	newargs = PyTuple_GetSlice(args, 1, n);
-	if (newargs == NULL)
-		return NULL;
-
-	s_object = cache_struct(fmt);
-	if (s_object == NULL) {
-		Py_DECREF(newargs);
-		return NULL;
-	}
-    	result = s_pack_into(s_object, newargs);
-	Py_DECREF(newargs);
-	Py_DECREF(s_object);
-	return result;
-}
-
-PyDoc_STRVAR(unpack_doc,
-"Unpack the string containing packed C structure data, according to fmt.\n\
-Requires len(string) == calcsize(fmt).");
-
-static PyObject *
-unpack(PyObject *self, PyObject *args)
-{
-	PyObject *s_object, *fmt, *inputstr, *result;
-
-	if (!PyArg_UnpackTuple(args, "unpack", 2, 2, &fmt, &inputstr))
-		return NULL;
-
-	s_object = cache_struct(fmt);
-	if (s_object == NULL)
-		return NULL;
-    	result = s_unpack(s_object, inputstr);
-	Py_DECREF(s_object);
-	return result;
-}
-
-PyDoc_STRVAR(unpack_from_doc,
-"Unpack the buffer, containing packed C structure data, according to\n\
-fmt, starting at offset. Requires len(buffer[offset:]) >= calcsize(fmt).");
-
-static PyObject *
-unpack_from(PyObject *self, PyObject *args, PyObject *kwds)
-{
-	PyObject *s_object, *fmt, *newargs, *result;
-	Py_ssize_t n = PyTuple_GET_SIZE(args);
-
-	if (n == 0) {
-		PyErr_SetString(PyExc_TypeError, "missing format argument");
-		return NULL;
-	}
-	fmt = PyTuple_GET_ITEM(args, 0);
-	newargs = PyTuple_GetSlice(args, 1, n);
-	if (newargs == NULL)
-		return NULL;
-
-	s_object = cache_struct(fmt);
-	if (s_object == NULL) {
-		Py_DECREF(newargs);
-		return NULL;
-	}
-    	result = s_unpack_from(s_object, newargs, kwds);
-	Py_DECREF(newargs);
-	Py_DECREF(s_object);
-	return result;
-}
-
-static struct PyMethodDef module_functions[] = {
-	{"_clearcache",	(PyCFunction)clearcache,	METH_NOARGS, 	clearcache_doc},
-	{"calcsize",	calcsize,	METH_O, 	calcsize_doc},
-	{"pack",	pack,		METH_VARARGS, 	pack_doc},
-	{"pack_into",	pack_into,	METH_VARARGS, 	pack_into_doc},
-	{"unpack",	unpack,       	METH_VARARGS, 	unpack_doc},
-	{"unpack_from",	(PyCFunction)unpack_from, 	
-			METH_VARARGS|METH_KEYWORDS, 	unpack_from_doc},
-	{NULL,	 NULL}		/* sentinel */
-};
-
-
-/* Module initialization */
-
-PyDoc_STRVAR(module_doc,
-"Functions to convert between Python values and C structs represented\n\
-as Python strings. It uses format strings (explained below) as compact\n\
-descriptions of the lay-out of the C structs and the intended conversion\n\
-to/from Python values.\n\
-\n\
-The remaining chars indicate types of args and must match exactly;\n\
-these can be preceded by a decimal repeat count:\n\
-  x: pad byte (no data); c:char; b:signed byte; B:unsigned byte;\n\
-  ?: _Bool (requires C99; if not available, char is used instead)\n\
-  h:short; H:unsigned short; i:int; I:unsigned int;\n\
-  l:long; L:unsigned long; f:float; d:double.\n\
-Special cases (preceding decimal count indicates length):\n\
-  s:string (array of char); p: pascal string (with count byte).\n\
-Special case (only available in native format):\n\
-  P:an integer type that is wide enough to hold a pointer.\n\
-Special case (not in native mode unless 'long long' in platform C):\n\
-  q:long long; Q:unsigned long long\n\
-Whitespace between formats is ignored.\n\
-\n\
-The variable struct.error is an exception raised on errors.\n");
-
-PyMODINIT_FUNC
-init_pvt_struct(void)
-{
-	PyObject *ver, *m;
-
-	ver = PyString_FromString("0.2");
-	if (ver == NULL)
-		return;
-
-	m = Py_InitModule3("_pvt_struct", module_functions, module_doc);
-	if (m == NULL)
-		return;
-
-	Py_TYPE(&PyStructType) = &PyType_Type;
-	if (PyType_Ready(&PyStructType) < 0)
-		return;
-
-	/* This speed trick can't be used until overflow masking goes
-	   away, because native endian always raises exceptions
-	   instead of overflow masking. */
-
-	/* Add some symbolic constants to the module */
-	if (StructError == NULL) {
-		StructError = PyErr_NewException("pyopencl._pvt_struct.error", NULL, NULL);
-		if (StructError == NULL)
-			return;
-	}
-
-	Py_INCREF(StructError);
-	PyModule_AddObject(m, "error", StructError);
-
-	Py_INCREF((PyObject*)&PyStructType);
-	PyModule_AddObject(m, "Struct", (PyObject*)&PyStructType);
-
-	PyModule_AddObject(m, "__version__", ver);
-
-	PyModule_AddIntConstant(m, "_PY_STRUCT_RANGE_CHECKING", 1);
-#ifdef PY_STRUCT_FLOAT_COERCE
-	PyModule_AddIntConstant(m, "_PY_STRUCT_FLOAT_COERCE", 1);
-#endif
-
-}
-
-// vim: noexpandtab:sw=8
diff --git a/src/wrapper/_pvt_struct_v3.cpp b/src/wrapper/_pvt_struct_v3.cpp
deleted file mode 100644
index 316062f1..00000000
--- a/src/wrapper/_pvt_struct_v3.cpp
+++ /dev/null
@@ -1,1749 +0,0 @@
-/* struct module -- pack values into and (out of) bytes objects */
-
-/* New version supporting byte order, alignment and size options,
-   character strings, and unsigned numbers */
-
-#define PY_SSIZE_T_CLEAN
-
-#include "Python.h"
-#include "structmember.h"
-#include <ctype.h>
-#include "numpy_init.hpp"
-
-namespace {
-extern PyTypeObject PyStructType;
-}
-
-/* The translation function for each format character is table driven */
-typedef struct _formatdef {
-    char format;
-    Py_ssize_t size;
-    Py_ssize_t alignment;
-    PyObject* (*unpack)(const char *,
-                        const struct _formatdef *);
-    int (*pack)(char *, PyObject *,
-                const struct _formatdef *);
-} formatdef;
-
-typedef struct _formatcode {
-    const struct _formatdef *fmtdef;
-    Py_ssize_t offset;
-    Py_ssize_t size;
-} formatcode;
-
-/* Struct object interface */
-
-typedef struct {
-    PyObject_HEAD
-    Py_ssize_t s_size;
-    Py_ssize_t s_len;
-    formatcode *s_codes;
-    PyObject *s_format;
-    PyObject *weakreflist; /* List of weak references */
-} PyStructObject;
-
-
-#define PyStruct_Check(op) PyObject_TypeCheck(op, &PyStructType)
-#define PyStruct_CheckExact(op) (Py_TYPE(op) == &PyStructType)
-
-
-/* Exception */
-
-static PyObject *StructError;
-
-
-/* Define various structs to figure out the alignments of types */
-
-
-typedef struct { char c; short x; } st_short;
-typedef struct { char c; int x; } st_int;
-typedef struct { char c; long x; } st_long;
-typedef struct { char c; float x; } st_float;
-typedef struct { char c; double x; } st_double;
-typedef struct { char c; void *x; } st_void_p;
-typedef struct { char c; size_t x; } st_size_t;
-
-#define SHORT_ALIGN (sizeof(st_short) - sizeof(short))
-#define INT_ALIGN (sizeof(st_int) - sizeof(int))
-#define LONG_ALIGN (sizeof(st_long) - sizeof(long))
-#define FLOAT_ALIGN (sizeof(st_float) - sizeof(float))
-#define DOUBLE_ALIGN (sizeof(st_double) - sizeof(double))
-#define VOID_P_ALIGN (sizeof(st_void_p) - sizeof(void *))
-#define SIZE_T_ALIGN (sizeof(st_size_t) - sizeof(size_t))
-
-/* We can't support q and Q in native mode unless the compiler does;
-   in std mode, they're 8 bytes on all platforms. */
-#ifdef HAVE_LONG_LONG
-typedef struct { char c; PY_LONG_LONG x; } s_long_long;
-#define LONG_LONG_ALIGN (sizeof(s_long_long) - sizeof(PY_LONG_LONG))
-#endif
-
-#if !defined(__cplusplus) && defined(HAVE_C99_BOOL)
-#define BOOL_TYPE _Bool
-typedef struct { char c; _Bool x; } s_bool;
-#define BOOL_ALIGN (sizeof(s_bool) - sizeof(BOOL_TYPE))
-#else
-#define BOOL_TYPE char
-#define BOOL_ALIGN 0
-#endif
-
-#define STRINGIFY(x)    #x
-
-#ifdef __powerc
-#pragma options align=reset
-#endif
-
-/* Helper for integer format codes: converts an arbitrary Python object to a
-   PyLongObject if possible, otherwise fails.  Caller should decref. */
-
-static PyObject *
-get_pylong(PyObject *v)
-{
-    assert(v != NULL);
-    if (!PyLong_Check(v)) {
-        /* Not an integer;  try to use __index__ to convert. */
-        if (PyIndex_Check(v)) {
-            v = PyNumber_Index(v);
-            if (v == NULL)
-                return NULL;
-        }
-        else {
-            PyErr_SetString(StructError,
-                            "required argument is not an integer");
-            return NULL;
-        }
-    }
-    else
-        Py_INCREF(v);
-
-    assert(PyLong_Check(v));
-    return v;
-}
-
-/* Helper routine to get a C long and raise the appropriate error if it isn't
-   one */
-
-static int
-get_long(PyObject *v, long *p)
-{
-    long x;
-
-    v = get_pylong(v);
-    if (v == NULL)
-        return -1;
-    assert(PyLong_Check(v));
-    x = PyLong_AsLong(v);
-    Py_DECREF(v);
-    if (x == (long)-1 && PyErr_Occurred()) {
-        if (PyErr_ExceptionMatches(PyExc_OverflowError))
-            PyErr_SetString(StructError,
-                            "argument out of range");
-        return -1;
-    }
-    *p = x;
-    return 0;
-}
-
-
-/* Same, but handling unsigned long */
-
-static int
-get_ulong(PyObject *v, unsigned long *p)
-{
-    unsigned long x;
-
-    v = get_pylong(v);
-    if (v == NULL)
-        return -1;
-    assert(PyLong_Check(v));
-    x = PyLong_AsUnsignedLong(v);
-    Py_DECREF(v);
-    if (x == (unsigned long)-1 && PyErr_Occurred()) {
-        if (PyErr_ExceptionMatches(PyExc_OverflowError))
-            PyErr_SetString(StructError,
-                            "argument out of range");
-        return -1;
-    }
-    *p = x;
-    return 0;
-}
-
-#ifdef HAVE_LONG_LONG
-
-/* Same, but handling native long long. */
-
-static int
-get_longlong(PyObject *v, PY_LONG_LONG *p)
-{
-    PY_LONG_LONG x;
-
-    v = get_pylong(v);
-    if (v == NULL)
-        return -1;
-    assert(PyLong_Check(v));
-    x = PyLong_AsLongLong(v);
-    Py_DECREF(v);
-    if (x == (PY_LONG_LONG)-1 && PyErr_Occurred()) {
-        if (PyErr_ExceptionMatches(PyExc_OverflowError))
-            PyErr_SetString(StructError,
-                            "argument out of range");
-        return -1;
-    }
-    *p = x;
-    return 0;
-}
-
-/* Same, but handling native unsigned long long. */
-
-static int
-get_ulonglong(PyObject *v, unsigned PY_LONG_LONG *p)
-{
-    unsigned PY_LONG_LONG x;
-
-    v = get_pylong(v);
-    if (v == NULL)
-        return -1;
-    assert(PyLong_Check(v));
-    x = PyLong_AsUnsignedLongLong(v);
-    Py_DECREF(v);
-    if (x == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred()) {
-        if (PyErr_ExceptionMatches(PyExc_OverflowError))
-            PyErr_SetString(StructError,
-                            "argument out of range");
-        return -1;
-    }
-    *p = x;
-    return 0;
-}
-
-#endif
-
-/* Same, but handling Py_ssize_t */
-
-static int
-get_ssize_t(PyObject *v, Py_ssize_t *p)
-{
-    Py_ssize_t x;
-
-    v = get_pylong(v);
-    if (v == NULL)
-        return -1;
-    assert(PyLong_Check(v));
-    x = PyLong_AsSsize_t(v);
-    Py_DECREF(v);
-    if (x == (Py_ssize_t)-1 && PyErr_Occurred()) {
-        if (PyErr_ExceptionMatches(PyExc_OverflowError))
-            PyErr_SetString(StructError,
-                            "argument out of range");
-        return -1;
-    }
-    *p = x;
-    return 0;
-}
-
-/* Same, but handling size_t */
-
-static int
-get_size_t(PyObject *v, size_t *p)
-{
-    size_t x;
-
-    v = get_pylong(v);
-    if (v == NULL)
-        return -1;
-    assert(PyLong_Check(v));
-    x = PyLong_AsSize_t(v);
-    Py_DECREF(v);
-    if (x == (size_t)-1 && PyErr_Occurred()) {
-        if (PyErr_ExceptionMatches(PyExc_OverflowError))
-            PyErr_SetString(StructError,
-                            "argument out of range");
-        return -1;
-    }
-    *p = x;
-    return 0;
-}
-
-
-#define RANGE_ERROR(x, f, flag, mask) return _range_error(f, flag)
-
-
-/* Floating point helpers */
-#if 0
-
-static PyObject *
-unpack_float(const char *p,  /* start of 4-byte string */
-         int le)             /* true for little-endian, false for big-endian */
-{
-    double x;
-
-    x = _PyFloat_Unpack4((unsigned char *)p, le);
-    if (x == -1.0 && PyErr_Occurred())
-        return NULL;
-    return PyFloat_FromDouble(x);
-}
-
-static PyObject *
-unpack_double(const char *p,  /* start of 8-byte string */
-          int le)         /* true for little-endian, false for big-endian */
-{
-    double x;
-
-    x = _PyFloat_Unpack8((unsigned char *)p, le);
-    if (x == -1.0 && PyErr_Occurred())
-        return NULL;
-    return PyFloat_FromDouble(x);
-}
-
-#endif
-
-/* Helper to format the range error exceptions */
-static int
-_range_error(const formatdef *f, int is_unsigned)
-{
-    /* ulargest is the largest unsigned value with f->size bytes.
-     * Note that the simpler:
-     *     ((size_t)1 << (f->size * 8)) - 1
-     * doesn't work when f->size == sizeof(size_t) because C doesn't
-     * define what happens when a left shift count is >= the number of
-     * bits in the integer being shifted; e.g., on some boxes it doesn't
-     * shift at all when they're equal.
-     */
-    const size_t ulargest = (size_t)-1 >> ((SIZEOF_SIZE_T - f->size)*8);
-    assert(f->size >= 1 && f->size <= SIZEOF_SIZE_T);
-    if (is_unsigned)
-        PyErr_Format(StructError,
-            "'%c' format requires 0 <= number <= %zu",
-            f->format,
-            ulargest);
-    else {
-        const Py_ssize_t largest = (Py_ssize_t)(ulargest >> 1);
-        PyErr_Format(StructError,
-            "'%c' format requires %zd <= number <= %zd",
-            f->format,
-            ~ largest,
-            largest);
-    }
-
-    return -1;
-}
-
-
-
-/* A large number of small routines follow, with names of the form
-
-   [bln][up]_TYPE
-
-   [bln] distiguishes among big-endian, little-endian and native.
-   [pu] distiguishes between pack (to struct) and unpack (from struct).
-   TYPE is one of char, byte, ubyte, etc.
-*/
-
-// {{{
-
-/* Native mode routines. ****************************************************/
-/* NOTE:
-   In all n[up]_<type> routines handling types larger than 1 byte, there is
-   *no* guarantee that the p pointer is properly aligned for each type,
-   therefore memcpy is called.  An intermediate variable is used to
-   compensate for big-endian architectures.
-   Normally both the intermediate variable and the memcpy call will be
-   skipped by C optimisation in little-endian architectures (gcc >= 2.91
-   does this). */
-
-static PyObject *
-nu_char(const char *p, const formatdef *f)
-{
-    return PyBytes_FromStringAndSize(p, 1);
-}
-
-static PyObject *
-nu_byte(const char *p, const formatdef *f)
-{
-    return PyLong_FromLong((long) *(signed char *)p);
-}
-
-static PyObject *
-nu_ubyte(const char *p, const formatdef *f)
-{
-    return PyLong_FromLong((long) *(unsigned char *)p);
-}
-
-static PyObject *
-nu_short(const char *p, const formatdef *f)
-{
-    short x;
-    memcpy((char *)&x, p, sizeof x);
-    return PyLong_FromLong((long)x);
-}
-
-static PyObject *
-nu_ushort(const char *p, const formatdef *f)
-{
-    unsigned short x;
-    memcpy((char *)&x, p, sizeof x);
-    return PyLong_FromLong((long)x);
-}
-
-static PyObject *
-nu_int(const char *p, const formatdef *f)
-{
-    int x;
-    memcpy((char *)&x, p, sizeof x);
-    return PyLong_FromLong((long)x);
-}
-
-static PyObject *
-nu_uint(const char *p, const formatdef *f)
-{
-    unsigned int x;
-    memcpy((char *)&x, p, sizeof x);
-#if (SIZEOF_LONG > SIZEOF_INT)
-    return PyLong_FromLong((long)x);
-#else
-    if (x <= ((unsigned int)LONG_MAX))
-        return PyLong_FromLong((long)x);
-    return PyLong_FromUnsignedLong((unsigned long)x);
-#endif
-}
-
-static PyObject *
-nu_long(const char *p, const formatdef *f)
-{
-    long x;
-    memcpy((char *)&x, p, sizeof x);
-    return PyLong_FromLong(x);
-}
-
-static PyObject *
-nu_ulong(const char *p, const formatdef *f)
-{
-    unsigned long x;
-    memcpy((char *)&x, p, sizeof x);
-    if (x <= LONG_MAX)
-        return PyLong_FromLong((long)x);
-    return PyLong_FromUnsignedLong(x);
-}
-
-static PyObject *
-nu_ssize_t(const char *p, const formatdef *f)
-{
-    Py_ssize_t x;
-    memcpy((char *)&x, p, sizeof x);
-    return PyLong_FromSsize_t(x);
-}
-
-static PyObject *
-nu_size_t(const char *p, const formatdef *f)
-{
-    size_t x;
-    memcpy((char *)&x, p, sizeof x);
-    return PyLong_FromSize_t(x);
-}
-
-
-/* Native mode doesn't support q or Q unless the platform C supports
-   long long (or, on Windows, __int64). */
-
-#ifdef HAVE_LONG_LONG
-
-static PyObject *
-nu_longlong(const char *p, const formatdef *f)
-{
-    PY_LONG_LONG x;
-    memcpy((char *)&x, p, sizeof x);
-    if (x >= LONG_MIN && x <= LONG_MAX)
-        return PyLong_FromLong(Py_SAFE_DOWNCAST(x, PY_LONG_LONG, long));
-    return PyLong_FromLongLong(x);
-}
-
-static PyObject *
-nu_ulonglong(const char *p, const formatdef *f)
-{
-    unsigned PY_LONG_LONG x;
-    memcpy((char *)&x, p, sizeof x);
-    if (x <= LONG_MAX)
-        return PyLong_FromLong(Py_SAFE_DOWNCAST(x, unsigned PY_LONG_LONG, long));
-    return PyLong_FromUnsignedLongLong(x);
-}
-
-#endif
-
-static PyObject *
-nu_bool(const char *p, const formatdef *f)
-{
-    BOOL_TYPE x;
-    memcpy((char *)&x, p, sizeof x);
-    return PyBool_FromLong(x != 0);
-}
-
-
-static PyObject *
-nu_float(const char *p, const formatdef *f)
-{
-    float x;
-    memcpy((char *)&x, p, sizeof x);
-    return PyFloat_FromDouble((double)x);
-}
-
-static PyObject *
-nu_double(const char *p, const formatdef *f)
-{
-    double x;
-    memcpy((char *)&x, p, sizeof x);
-    return PyFloat_FromDouble(x);
-}
-
-static PyObject *
-nu_complex_float(const char *p, const formatdef *f)
-{
-    float re, im;
-    memcpy((char *)&re, p, sizeof re);
-    memcpy((char *)&im, p+sizeof re, sizeof im);
-    return PyComplex_FromDoubles((double)re, (double) im);
-}
-
-static PyObject *
-nu_complex_double(const char *p, const formatdef *f)
-{
-    double re, im;
-    memcpy((char *)&re, p, sizeof re);
-    memcpy((char *)&im, p+sizeof re, sizeof im);
-    return PyComplex_FromDoubles(re, im);
-}
-
-static PyObject *
-nu_void_p(const char *p, const formatdef *f)
-{
-    void *x;
-    memcpy((char *)&x, p, sizeof x);
-    return PyLong_FromVoidPtr(x);
-}
-
-static int
-np_byte(char *p, PyObject *v, const formatdef *f)
-{
-    long x;
-    if (get_long(v, &x) < 0)
-        return -1;
-    if (x < -128 || x > 127){
-        PyErr_SetString(StructError,
-                        "byte format requires -128 <= number <= 127");
-        return -1;
-    }
-    *p = (char)x;
-    return 0;
-}
-
-static int
-np_ubyte(char *p, PyObject *v, const formatdef *f)
-{
-    long x;
-    if (get_long(v, &x) < 0)
-        return -1;
-    if (x < 0 || x > 255){
-        PyErr_SetString(StructError,
-                        "ubyte format requires 0 <= number <= 255");
-        return -1;
-    }
-    *p = (char)x;
-    return 0;
-}
-
-static int
-np_char(char *p, PyObject *v, const formatdef *f)
-{
-    if (!PyBytes_Check(v) || PyBytes_Size(v) != 1) {
-        PyErr_SetString(StructError,
-                        "char format requires a bytes object of length 1");
-        return -1;
-    }
-    *p = *PyBytes_AsString(v);
-    return 0;
-}
-
-static int
-np_short(char *p, PyObject *v, const formatdef *f)
-{
-    long x;
-    short y;
-    if (get_long(v, &x) < 0)
-        return -1;
-    if (x < SHRT_MIN || x > SHRT_MAX){
-        PyErr_SetString(StructError,
-                        "short format requires " STRINGIFY(SHRT_MIN)
-                        " <= number <= " STRINGIFY(SHRT_MAX));
-        return -1;
-    }
-    y = (short)x;
-    memcpy(p, (char *)&y, sizeof y);
-    return 0;
-}
-
-static int
-np_ushort(char *p, PyObject *v, const formatdef *f)
-{
-    long x;
-    unsigned short y;
-    if (get_long(v, &x) < 0)
-        return -1;
-    if (x < 0 || x > USHRT_MAX){
-        PyErr_SetString(StructError,
-                        "ushort format requires 0 <= number <= " STRINGIFY(USHRT_MAX));
-        return -1;
-    }
-    y = (unsigned short)x;
-    memcpy(p, (char *)&y, sizeof y);
-    return 0;
-}
-
-static int
-np_int(char *p, PyObject *v, const formatdef *f)
-{
-    long x;
-    int y;
-    if (get_long(v, &x) < 0)
-        return -1;
-#if (SIZEOF_LONG > SIZEOF_INT)
-    if ((x < ((long)INT_MIN)) || (x > ((long)INT_MAX)))
-        RANGE_ERROR(x, f, 0, -1);
-#endif
-    y = (int)x;
-    memcpy(p, (char *)&y, sizeof y);
-    return 0;
-}
-
-static int
-np_uint(char *p, PyObject *v, const formatdef *f)
-{
-    unsigned long x;
-    unsigned int y;
-    if (get_ulong(v, &x) < 0)
-        return -1;
-    y = (unsigned int)x;
-#if (SIZEOF_LONG > SIZEOF_INT)
-    if (x > ((unsigned long)UINT_MAX))
-        RANGE_ERROR(y, f, 1, -1);
-#endif
-    memcpy(p, (char *)&y, sizeof y);
-    return 0;
-}
-
-static int
-np_long(char *p, PyObject *v, const formatdef *f)
-{
-    long x;
-    if (get_long(v, &x) < 0)
-        return -1;
-    memcpy(p, (char *)&x, sizeof x);
-    return 0;
-}
-
-static int
-np_ulong(char *p, PyObject *v, const formatdef *f)
-{
-    unsigned long x;
-    if (get_ulong(v, &x) < 0)
-        return -1;
-    memcpy(p, (char *)&x, sizeof x);
-    return 0;
-}
-
-static int
-np_ssize_t(char *p, PyObject *v, const formatdef *f)
-{
-    Py_ssize_t x;
-    if (get_ssize_t(v, &x) < 0)
-        return -1;
-    memcpy(p, (char *)&x, sizeof x);
-    return 0;
-}
-
-static int
-np_size_t(char *p, PyObject *v, const formatdef *f)
-{
-    size_t x;
-    if (get_size_t(v, &x) < 0)
-        return -1;
-    memcpy(p, (char *)&x, sizeof x);
-    return 0;
-}
-
-#ifdef HAVE_LONG_LONG
-
-static int
-np_longlong(char *p, PyObject *v, const formatdef *f)
-{
-    PY_LONG_LONG x;
-    if (get_longlong(v, &x) < 0)
-        return -1;
-    memcpy(p, (char *)&x, sizeof x);
-    return 0;
-}
-
-static int
-np_ulonglong(char *p, PyObject *v, const formatdef *f)
-{
-    unsigned PY_LONG_LONG x;
-    if (get_ulonglong(v, &x) < 0)
-        return -1;
-    memcpy(p, (char *)&x, sizeof x);
-    return 0;
-}
-#endif
-
-
-static int
-np_bool(char *p, PyObject *v, const formatdef *f)
-{
-    int y;
-    BOOL_TYPE x;
-    y = PyObject_IsTrue(v);
-    if (y < 0)
-        return -1;
-    x = y;
-    memcpy(p, (char *)&x, sizeof x);
-    return 0;
-}
-
-static int
-np_float(char *p, PyObject *v, const formatdef *f)
-{
-    float x = (float)PyFloat_AsDouble(v);
-    if (x == -1 && PyErr_Occurred()) {
-        PyErr_SetString(StructError,
-                        "required argument is not a float");
-        return -1;
-    }
-    memcpy(p, (char *)&x, sizeof x);
-    return 0;
-}
-
-static int
-np_double(char *p, PyObject *v, const formatdef *f)
-{
-    double x = PyFloat_AsDouble(v);
-    if (x == -1 && PyErr_Occurred()) {
-        PyErr_SetString(StructError,
-                        "required argument is not a float");
-        return -1;
-    }
-    memcpy(p, (char *)&x, sizeof(double));
-    return 0;
-}
-
-static int
-np_complex_float(char *p, PyObject *v, const formatdef *f)
-{
-    if (PyArray_IsZeroDim(v)) {
-        PyObject *v_cast = PyArray_Cast(
-                reinterpret_cast<PyArrayObject *>(v),
-                NPY_CFLOAT);
-        if (!v_cast)
-            return -1;
-        memcpy(p, PyArray_DATA(v_cast), PyArray_NBYTES(v_cast));
-        Py_DECREF(v_cast);
-    }
-    else {
-        float re = 0.0f;
-        float im = 0.0f;
-        Py_complex cplx = PyComplex_AsCComplex(v);
-        if (PyErr_Occurred()) {
-            PyErr_SetString(StructError,
-                    "required argument is not a complex");
-            return -1;
-        }
-
-        re = (float)cplx.real;
-        im = (float)cplx.imag;
-        memcpy(p, (char *)&re, sizeof re);
-        memcpy(p+sizeof re, (char *)&im, sizeof im);
-    }
-    return 0;
-}
-
-static int
-np_complex_double(char *p, PyObject *v, const formatdef *f)
-{
-    if (PyArray_IsZeroDim(v)) {
-        PyObject *v_cast = PyArray_Cast(
-                reinterpret_cast<PyArrayObject *>(v),
-                NPY_CDOUBLE);
-        if (!v_cast)
-            return -1;
-        memcpy(p, PyArray_DATA(v_cast), PyArray_NBYTES(v_cast));
-        Py_DECREF(v_cast);
-    }
-    else {
-        double re = 0.0;
-        double im = 0.0;
-        Py_complex cplx = PyComplex_AsCComplex(v);
-        if (PyErr_Occurred()) {
-            PyErr_SetString(StructError,
-                    "required argument is not a complex");
-            return -1;
-        }
-        re = cplx.real;
-        im = cplx.imag;
-        memcpy(p, (char *)&re, sizeof re);
-        memcpy(p+sizeof re, (char *)&im, sizeof im);
-    }
-    return 0;
-}
-
-
-static int
-np_void_p(char *p, PyObject *v, const formatdef *f)
-{
-    void *x;
-
-    v = get_pylong(v);
-    if (v == NULL)
-        return -1;
-    assert(PyLong_Check(v));
-    x = PyLong_AsVoidPtr(v);
-    Py_DECREF(v);
-    if (x == NULL && PyErr_Occurred())
-        return -1;
-    memcpy(p, (char *)&x, sizeof x);
-    return 0;
-}
-
-static formatdef native_table[] = {
-    {'x',       sizeof(char),   0,              NULL},
-    {'b',       sizeof(char),   0,              nu_byte,        np_byte},
-    {'B',       sizeof(char),   0,              nu_ubyte,       np_ubyte},
-    {'c',       sizeof(char),   0,              nu_char,        np_char},
-    {'s',       sizeof(char),   0,              NULL},
-    {'p',       sizeof(char),   0,              NULL},
-    {'h',       sizeof(short),  SHORT_ALIGN,    nu_short,       np_short},
-    {'H',       sizeof(short),  SHORT_ALIGN,    nu_ushort,      np_ushort},
-    {'i',       sizeof(int),    INT_ALIGN,      nu_int,         np_int},
-    {'I',       sizeof(int),    INT_ALIGN,      nu_uint,        np_uint},
-    {'l',       sizeof(long),   LONG_ALIGN,     nu_long,        np_long},
-    {'L',       sizeof(long),   LONG_ALIGN,     nu_ulong,       np_ulong},
-    {'n',       sizeof(size_t), SIZE_T_ALIGN,   nu_ssize_t,     np_ssize_t},
-    {'N',       sizeof(size_t), SIZE_T_ALIGN,   nu_size_t,      np_size_t},
-#ifdef HAVE_LONG_LONG
-    {'q',       sizeof(PY_LONG_LONG), LONG_LONG_ALIGN, nu_longlong, np_longlong},
-    {'Q',       sizeof(PY_LONG_LONG), LONG_LONG_ALIGN, nu_ulonglong,np_ulonglong},
-#endif
-    {'?',       sizeof(BOOL_TYPE),      BOOL_ALIGN,     nu_bool,        np_bool},
-    {'f',       sizeof(float),  FLOAT_ALIGN,    nu_float,       np_float},
-    {'d',       sizeof(double), DOUBLE_ALIGN,   nu_double,      np_double},
-    {'F',       2*sizeof(float),  FLOAT_ALIGN,    nu_complex_float,       np_complex_float},
-    {'D',       2*sizeof(double), DOUBLE_ALIGN,   nu_complex_double,      np_complex_double},
-    {'P',       sizeof(void *), VOID_P_ALIGN,   nu_void_p,      np_void_p},
-    {0}
-};
-
-// }}}
-
-static const formatdef *
-whichtable(char **pfmt)
-{
-    const char *fmt = (*pfmt)++; /* May be backed out of later */
-    switch (*fmt) {
-    default:
-        --*pfmt; /* Back out of pointer increment */
-        /* Fall through */
-    case '@':
-        return native_table;
-    }
-}
-
-
-/* Get the table entry for a format code */
-
-static const formatdef *
-getentry(int c, const formatdef *f)
-{
-    for (; f->format != '\0'; f++) {
-        if (f->format == c) {
-            return f;
-        }
-    }
-    PyErr_SetString(StructError, "bad char in struct format");
-    return NULL;
-}
-
-
-/* Align a size according to a format code.  Return -1 on overflow. */
-
-static Py_ssize_t
-align(Py_ssize_t size, char c, const formatdef *e)
-{
-    Py_ssize_t extra;
-
-    if (e->format == c) {
-        if (e->alignment && size > 0) {
-            extra = (e->alignment - 1) - (size - 1) % (e->alignment);
-            if (extra > PY_SSIZE_T_MAX - size)
-                return -1;
-            size += extra;
-        }
-    }
-    return size;
-}
-
-
-/* calculate the size of a format string */
-
-static int
-prepare_s(PyStructObject *self)
-{
-    const formatdef *f;
-    const formatdef *e;
-    formatcode *codes;
-
-    const char *s;
-    const char *fmt;
-    char c;
-    Py_ssize_t size, len, num, itemsize;
-
-    fmt = PyBytes_AS_STRING(self->s_format);
-
-    f = whichtable((char **)&fmt);
-
-    s = fmt;
-    size = 0;
-    len = 0;
-    while ((c = *s++) != '\0') {
-        if (isspace(Py_CHARMASK(c)))
-            continue;
-        if ('0' <= c && c <= '9') {
-            num = c - '0';
-            while ('0' <= (c = *s++) && c <= '9') {
-                /* overflow-safe version of
-                   if (num*10 + (c - '0') > PY_SSIZE_T_MAX) { ... } */
-                if (num >= PY_SSIZE_T_MAX / 10 && (
-                        num > PY_SSIZE_T_MAX / 10 ||
-                        (c - '0') > PY_SSIZE_T_MAX % 10))
-                    goto overflow;
-                num = num*10 + (c - '0');
-            }
-            if (c == '\0') {
-                PyErr_SetString(StructError,
-                                "repeat count given without format specifier");
-                return -1;
-            }
-        }
-        else
-            num = 1;
-
-        e = getentry(c, f);
-        if (e == NULL)
-            return -1;
-
-        switch (c) {
-            case 's': /* fall through */
-            case 'p': len++; break;
-            case 'x': break;
-            default: len += num; break;
-        }
-
-        itemsize = e->size;
-        size = align(size, c, e);
-        if (size == -1)
-            goto overflow;
-
-        /* if (size + num * itemsize > PY_SSIZE_T_MAX) { ... } */
-        if (num > (PY_SSIZE_T_MAX - size) / itemsize)
-            goto overflow;
-        size += num * itemsize;
-    }
-
-    /* check for overflow */
-    if ((len + 1) > (PY_SSIZE_T_MAX / sizeof(formatcode))) {
-        PyErr_NoMemory();
-        return -1;
-    }
-
-    self->s_size = size;
-    self->s_len = len;
-    codes = (formatcode *) PyMem_MALLOC((len + 1) * sizeof(formatcode));
-    if (codes == NULL) {
-        PyErr_NoMemory();
-        return -1;
-    }
-    /* Free any s_codes value left over from a previous initialization. */
-    if (self->s_codes != NULL)
-        PyMem_FREE(self->s_codes);
-    self->s_codes = codes;
-
-    s = fmt;
-    size = 0;
-    while ((c = *s++) != '\0') {
-        if (isspace(Py_CHARMASK(c)))
-            continue;
-        if ('0' <= c && c <= '9') {
-            num = c - '0';
-            while ('0' <= (c = *s++) && c <= '9')
-                num = num*10 + (c - '0');
-            if (c == '\0')
-                break;
-        }
-        else
-            num = 1;
-
-        e = getentry(c, f);
-
-        size = align(size, c, e);
-        if (c == 's' || c == 'p') {
-            codes->offset = size;
-            codes->size = num;
-            codes->fmtdef = e;
-            codes++;
-            size += num;
-        } else if (c == 'x') {
-            size += num;
-        } else {
-            while (--num >= 0) {
-                codes->offset = size;
-                codes->size = e->size;
-                codes->fmtdef = e;
-                codes++;
-                size += e->size;
-            }
-        }
-    }
-    codes->fmtdef = NULL;
-    codes->offset = size;
-    codes->size = 0;
-
-    return 0;
-
-  overflow:
-    PyErr_SetString(StructError,
-                    "total struct size too long");
-    return -1;
-}
-
-static PyObject *
-s_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
-    PyObject *self;
-
-    assert(type != NULL && type->tp_alloc != NULL);
-
-    self = type->tp_alloc(type, 0);
-    if (self != NULL) {
-        PyStructObject *s = (PyStructObject*)self;
-        Py_INCREF(Py_None);
-        s->s_format = Py_None;
-        s->s_codes = NULL;
-        s->s_size = -1;
-        s->s_len = -1;
-    }
-    return self;
-}
-
-static int
-s_init(PyObject *self, PyObject *args, PyObject *kwds)
-{
-    PyStructObject *soself = (PyStructObject *)self;
-    PyObject *o_format = NULL;
-    int ret = 0;
-    static char *kwlist[] = {"format", 0};
-
-    assert(PyStruct_Check(self));
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:Struct", kwlist,
-                                     &o_format))
-        return -1;
-
-    if (PyUnicode_Check(o_format)) {
-        o_format = PyUnicode_AsASCIIString(o_format);
-        if (o_format == NULL)
-            return -1;
-    }
-    /* XXX support buffer interface, too */
-    else {
-        Py_INCREF(o_format);
-    }
-
-    if (!PyBytes_Check(o_format)) {
-        Py_DECREF(o_format);
-        PyErr_Format(PyExc_TypeError,
-                     "Struct() argument 1 must be a bytes object, not %.200s",
-                     Py_TYPE(o_format)->tp_name);
-        return -1;
-    }
-
-    Py_CLEAR(soself->s_format);
-    soself->s_format = o_format;
-
-    ret = prepare_s(soself);
-    return ret;
-}
-
-static void
-s_dealloc(PyStructObject *s)
-{
-    if (s->weakreflist != NULL)
-        PyObject_ClearWeakRefs((PyObject *)s);
-    if (s->s_codes != NULL) {
-        PyMem_FREE(s->s_codes);
-    }
-    Py_XDECREF(s->s_format);
-    Py_TYPE(s)->tp_free((PyObject *)s);
-}
-
-static PyObject *
-s_unpack_internal(PyStructObject *soself, char *startfrom) {
-    formatcode *code;
-    Py_ssize_t i = 0;
-    PyObject *result = PyTuple_New(soself->s_len);
-    if (result == NULL)
-        return NULL;
-
-    for (code = soself->s_codes; code->fmtdef != NULL; code++) {
-        PyObject *v;
-        const formatdef *e = code->fmtdef;
-        const char *res = startfrom + code->offset;
-        if (e->format == 's') {
-            v = PyBytes_FromStringAndSize(res, code->size);
-        } else if (e->format == 'p') {
-            Py_ssize_t n = *(unsigned char*)res;
-            if (n >= code->size)
-                n = code->size - 1;
-            v = PyBytes_FromStringAndSize(res + 1, n);
-        } else {
-            v = e->unpack(res, e);
-        }
-        if (v == NULL)
-            goto fail;
-        PyTuple_SET_ITEM(result, i++, v);
-    }
-
-    return result;
-fail:
-    Py_DECREF(result);
-    return NULL;
-}
-
-
-PyDoc_STRVAR(s_unpack__doc__,
-"S.unpack(buffer) -> (v1, v2, ...)\n\
-\n\
-Return a tuple containing values unpacked according to the format\n\
-string S.format.  Requires len(buffer) == S.size.  See help(struct)\n\
-for more on format strings.");
-
-static PyObject *
-s_unpack(PyObject *self, PyObject *input)
-{
-    Py_buffer vbuf;
-    PyObject *result;
-    PyStructObject *soself = (PyStructObject *)self;
-
-    assert(PyStruct_Check(self));
-    assert(soself->s_codes != NULL);
-    if (PyObject_GetBuffer(input, &vbuf, PyBUF_SIMPLE) < 0)
-        return NULL;
-    if (vbuf.len != soself->s_size) {
-        PyErr_Format(StructError,
-                     "unpack requires a bytes object of length %zd",
-                     soself->s_size);
-        PyBuffer_Release(&vbuf);
-        return NULL;
-    }
-    result = s_unpack_internal(soself, (char *) vbuf.buf);
-    PyBuffer_Release(&vbuf);
-    return result;
-}
-
-PyDoc_STRVAR(s_unpack_from__doc__,
-"S.unpack_from(buffer, offset=0) -> (v1, v2, ...)\n\
-\n\
-Return a tuple containing values unpacked according to the format\n\
-string S.format.  Requires len(buffer[offset:]) >= S.size.  See\n\
-help(struct) for more on format strings.");
-
-static PyObject *
-s_unpack_from(PyObject *self, PyObject *args, PyObject *kwds)
-{
-    static char *kwlist[] = {"buffer", "offset", 0};
-
-    PyObject *input;
-    Py_ssize_t offset = 0;
-    Py_buffer vbuf;
-    PyObject *result;
-    PyStructObject *soself = (PyStructObject *)self;
-
-    assert(PyStruct_Check(self));
-    assert(soself->s_codes != NULL);
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds,
-                                     "O|n:unpack_from", kwlist,
-                                     &input, &offset))
-        return NULL;
-    if (PyObject_GetBuffer(input, &vbuf, PyBUF_SIMPLE) < 0)
-        return NULL;
-    if (offset < 0)
-        offset += vbuf.len;
-    if (offset < 0 || vbuf.len - offset < soself->s_size) {
-        PyErr_Format(StructError,
-            "unpack_from requires a buffer of at least %zd bytes",
-            soself->s_size);
-        PyBuffer_Release(&vbuf);
-        return NULL;
-    }
-    result = s_unpack_internal(soself, (char*)vbuf.buf + offset);
-    PyBuffer_Release(&vbuf);
-    return result;
-}
-
-
-/*
- * Guts of the pack function.
- *
- * Takes a struct object, a tuple of arguments, and offset in that tuple of
- * argument for where to start processing the arguments for packing, and a
- * character buffer for writing the packed string.  The caller must insure
- * that the buffer may contain the required length for packing the arguments.
- * 0 is returned on success, 1 is returned if there is an error.
- *
- */
-static int
-s_pack_internal(PyStructObject *soself, PyObject *args, int offset, char* buf)
-{
-    formatcode *code;
-    /* XXX(nnorwitz): why does i need to be a local?  can we use
-       the offset parameter or do we need the wider width? */
-    Py_ssize_t i;
-
-    memset(buf, '\0', soself->s_size);
-    i = offset;
-    for (code = soself->s_codes; code->fmtdef != NULL; code++) {
-        Py_ssize_t n;
-        PyObject *v = PyTuple_GET_ITEM(args, i++);
-        const formatdef *e = code->fmtdef;
-        char *res = buf + code->offset;
-        if (e->format == 's') {
-            int isstring;
-            void *p;
-            if (PyBytes_Check(v)) {
-                n = PyBytes_GET_SIZE(v);
-                p = PyBytes_AS_STRING(v);
-
-                if (n > code->size)
-                    n = code->size;
-                if (n > 0)
-                    memcpy(res, p, n);
-            } else if (PyByteArray_Check(v)) {
-                n = PyByteArray_GET_SIZE(v);
-                p = PyByteArray_AS_STRING(v);
-
-                if (n > code->size)
-                    n = code->size;
-                if (n > 0)
-                    memcpy(res, p, n);
-            } else if (PyObject_CheckBuffer(v)) {
-                Py_buffer view;
-                int gb_result = PyObject_GetBuffer(v, &view, PyBUF_SIMPLE);
-
-                if (gb_result == -1)
-                    return gb_result;
-
-                n = view.len;
-                if (n > code->size)
-                    n = code->size;
-                if (n > 0)
-                    memcpy(res, view.buf, n);
-
-                PyBuffer_Release(&view);
-            } else {
-                PyErr_SetString(StructError,
-                                "argument for 's' must be a bytes object");
-                return -1;
-            }
-        } else if (e->format == 'p') {
-            int isstring;
-            void *p;
-            isstring = PyBytes_Check(v);
-            if (!isstring && !PyByteArray_Check(v)) {
-                PyErr_SetString(StructError,
-                                "argument for 'p' must be a bytes object");
-                return -1;
-            }
-            if (isstring) {
-                n = PyBytes_GET_SIZE(v);
-                p = PyBytes_AS_STRING(v);
-            }
-            else {
-                n = PyByteArray_GET_SIZE(v);
-                p = PyByteArray_AS_STRING(v);
-            }
-            if (n > (code->size - 1))
-                n = code->size - 1;
-            if (n > 0)
-                memcpy(res + 1, p, n);
-            if (n > 255)
-                n = 255;
-            *res = Py_SAFE_DOWNCAST(n, Py_ssize_t, unsigned char);
-        } else {
-            if (e->pack(res, v, e) < 0) {
-                if (PyLong_Check(v) && PyErr_ExceptionMatches(PyExc_OverflowError))
-                    PyErr_SetString(StructError,
-                                    "long too large to convert to int");
-                return -1;
-            }
-        }
-    }
-
-    /* Success */
-    return 0;
-}
-
-
-PyDoc_STRVAR(s_pack__doc__,
-"S.pack(v1, v2, ...) -> bytes\n\
-\n\
-Return a bytes object containing values v1, v2, ... packed according\n\
-to the format string S.format.  See help(struct) for more on format\n\
-strings.");
-
-static PyObject *
-s_pack(PyObject *self, PyObject *args)
-{
-    PyStructObject *soself;
-    PyObject *result;
-
-    /* Validate arguments. */
-    soself = (PyStructObject *)self;
-    assert(PyStruct_Check(self));
-    assert(soself->s_codes != NULL);
-    if (PyTuple_GET_SIZE(args) != soself->s_len)
-    {
-        PyErr_Format(StructError,
-            "pack requires exactly %zd arguments", soself->s_len);
-        return NULL;
-    }
-
-    /* Allocate a new string */
-    result = PyBytes_FromStringAndSize((char *)NULL, soself->s_size);
-    if (result == NULL)
-        return NULL;
-
-    /* Call the guts */
-    if ( s_pack_internal(soself, args, 0, PyBytes_AS_STRING(result)) != 0 ) {
-        Py_DECREF(result);
-        return NULL;
-    }
-
-    return result;
-}
-
-PyDoc_STRVAR(s_pack_into__doc__,
-"S.pack_into(buffer, offset, v1, v2, ...)\n\
-\n\
-Pack the values v1, v2, ... according to the format string S.format\n\
-and write the packed bytes into the writable buffer buf starting at\n\
-offset.  Note that the offset is a required argument.  See\n\
-help(struct) for more on format strings.");
-
-static PyObject *
-s_pack_into(PyObject *self, PyObject *args)
-{
-    PyStructObject *soself;
-    char *buffer;
-    Py_ssize_t buffer_len, offset;
-
-    /* Validate arguments.  +1 is for the first arg as buffer. */
-    soself = (PyStructObject *)self;
-    assert(PyStruct_Check(self));
-    assert(soself->s_codes != NULL);
-    if (PyTuple_GET_SIZE(args) != (soself->s_len + 2))
-    {
-        PyErr_Format(StructError,
-                     "pack_into requires exactly %zd arguments",
-                     (soself->s_len + 2));
-        return NULL;
-    }
-
-    /* Extract a writable memory buffer from the first argument */
-    if ( PyObject_AsWriteBuffer(PyTuple_GET_ITEM(args, 0),
-                                                            (void**)&buffer, &buffer_len) == -1 ) {
-        return NULL;
-    }
-    assert( buffer_len >= 0 );
-
-    /* Extract the offset from the first argument */
-    offset = PyNumber_AsSsize_t(PyTuple_GET_ITEM(args, 1), PyExc_IndexError);
-    if (offset == -1 && PyErr_Occurred())
-        return NULL;
-
-    /* Support negative offsets. */
-    if (offset < 0)
-        offset += buffer_len;
-
-    /* Check boundaries */
-    if (offset < 0 || (buffer_len - offset) < soself->s_size) {
-        PyErr_Format(StructError,
-                     "pack_into requires a buffer of at least %zd bytes",
-                     soself->s_size);
-        return NULL;
-    }
-
-    /* Call the guts */
-    if ( s_pack_internal(soself, args, 2, buffer + offset) != 0 ) {
-        return NULL;
-    }
-
-    Py_RETURN_NONE;
-}
-
-static PyObject *
-s_get_format(PyStructObject *self, void *unused)
-{
-    Py_INCREF(self->s_format);
-    return self->s_format;
-}
-
-static PyObject *
-s_get_size(PyStructObject *self, void *unused)
-{
-    return PyLong_FromSsize_t(self->s_size);
-}
-
-/* List of functions */
-
-static struct PyMethodDef s_methods[] = {
-    {"pack",            s_pack,         METH_VARARGS, s_pack__doc__},
-    {"pack_into",       s_pack_into,    METH_VARARGS, s_pack_into__doc__},
-    {"unpack",          s_unpack,       METH_O, s_unpack__doc__},
-    {"unpack_from",     (PyCFunction)s_unpack_from, METH_VARARGS|METH_KEYWORDS,
-                    s_unpack_from__doc__},
-    {NULL,       NULL}          /* sentinel */
-};
-
-PyDoc_STRVAR(s__doc__,
-"Struct(fmt) --> compiled struct object\n"
-"\n"
-"Return a new Struct object which writes and reads binary data according to\n"
-"the format string fmt.  See help(struct) for more on format strings.");
-
-#define OFF(x) offsetof(PyStructObject, x)
-
-static PyGetSetDef s_getsetlist[] = {
-    {"format", (getter)s_get_format, (setter)NULL, "struct format string", NULL},
-    {"size", (getter)s_get_size, (setter)NULL, "struct size in bytes", NULL},
-    {NULL} /* sentinel */
-};
-
-namespace {
-PyTypeObject PyStructType = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "Struct",
-    sizeof(PyStructObject),
-    0,
-    (destructor)s_dealloc,      /* tp_dealloc */
-    0,                                          /* tp_print */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-    0,                                          /* tp_reserved */
-    0,                                          /* tp_repr */
-    0,                                          /* tp_as_number */
-    0,                                          /* tp_as_sequence */
-    0,                                          /* tp_as_mapping */
-    0,                                          /* tp_hash */
-    0,                                          /* tp_call */
-    0,                                          /* tp_str */
-    PyObject_GenericGetAttr,            /* tp_getattro */
-    PyObject_GenericSetAttr,            /* tp_setattro */
-    0,                                          /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
-    s__doc__,                           /* tp_doc */
-    0,                                          /* tp_traverse */
-    0,                                          /* tp_clear */
-    0,                                          /* tp_richcompare */
-    offsetof(PyStructObject, weakreflist),      /* tp_weaklistoffset */
-    0,                                          /* tp_iter */
-    0,                                          /* tp_iternext */
-    s_methods,                          /* tp_methods */
-    NULL,                               /* tp_members */
-    s_getsetlist,               /* tp_getset */
-    0,                                          /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    s_init,                             /* tp_init */
-    PyType_GenericAlloc,/* tp_alloc */
-    s_new,                              /* tp_new */
-    PyObject_Del,               /* tp_free */
-};
-}
-
-
-/* ---- Standalone functions  ---- */
-
-#define MAXCACHE 100
-static PyObject *cache = NULL;
-
-static PyObject *
-cache_struct(PyObject *fmt)
-{
-    PyObject * s_object;
-
-    if (cache == NULL) {
-        cache = PyDict_New();
-        if (cache == NULL)
-            return NULL;
-    }
-
-    s_object = PyDict_GetItem(cache, fmt);
-    if (s_object != NULL) {
-        Py_INCREF(s_object);
-        return s_object;
-    }
-
-    s_object = PyObject_CallFunctionObjArgs((PyObject *)(&PyStructType), fmt, NULL);
-    if (s_object != NULL) {
-        if (PyDict_Size(cache) >= MAXCACHE)
-            PyDict_Clear(cache);
-        /* Attempt to cache the result */
-        if (PyDict_SetItem(cache, fmt, s_object) == -1)
-            PyErr_Clear();
-    }
-    return s_object;
-}
-
-PyDoc_STRVAR(clearcache_doc,
-"Clear the internal cache.");
-
-static PyObject *
-clearcache(PyObject *self)
-{
-    Py_CLEAR(cache);
-    Py_RETURN_NONE;
-}
-
-PyDoc_STRVAR(calcsize_doc,
-"calcsize(fmt) -> integer\n\
-\n\
-Return size in bytes of the struct described by the format string fmt.");
-
-static PyObject *
-calcsize(PyObject *self, PyObject *fmt)
-{
-    Py_ssize_t n;
-    PyObject *s_object = cache_struct(fmt);
-    if (s_object == NULL)
-        return NULL;
-    n = ((PyStructObject *)s_object)->s_size;
-    Py_DECREF(s_object);
-    return PyLong_FromSsize_t(n);
-}
-
-PyDoc_STRVAR(pack_doc,
-"pack(fmt, v1, v2, ...) -> bytes\n\
-\n\
-Return a bytes object containing the values v1, v2, ... packed according\n\
-to the format string fmt.  See help(struct) for more on format strings.");
-
-static PyObject *
-pack(PyObject *self, PyObject *args)
-{
-    PyObject *s_object, *fmt, *newargs, *result;
-    Py_ssize_t n = PyTuple_GET_SIZE(args);
-
-    if (n == 0) {
-        PyErr_SetString(PyExc_TypeError, "missing format argument");
-        return NULL;
-    }
-    fmt = PyTuple_GET_ITEM(args, 0);
-    newargs = PyTuple_GetSlice(args, 1, n);
-    if (newargs == NULL)
-        return NULL;
-
-    s_object = cache_struct(fmt);
-    if (s_object == NULL) {
-        Py_DECREF(newargs);
-        return NULL;
-    }
-    result = s_pack(s_object, newargs);
-    Py_DECREF(newargs);
-    Py_DECREF(s_object);
-    return result;
-}
-
-PyDoc_STRVAR(pack_into_doc,
-"pack_into(fmt, buffer, offset, v1, v2, ...)\n\
-\n\
-Pack the values v1, v2, ... according to the format string fmt and write\n\
-the packed bytes into the writable buffer buf starting at offset.  Note\n\
-that the offset is a required argument.  See help(struct) for more\n\
-on format strings.");
-
-static PyObject *
-pack_into(PyObject *self, PyObject *args)
-{
-    PyObject *s_object, *fmt, *newargs, *result;
-    Py_ssize_t n = PyTuple_GET_SIZE(args);
-
-    if (n == 0) {
-        PyErr_SetString(PyExc_TypeError, "missing format argument");
-        return NULL;
-    }
-    fmt = PyTuple_GET_ITEM(args, 0);
-    newargs = PyTuple_GetSlice(args, 1, n);
-    if (newargs == NULL)
-        return NULL;
-
-    s_object = cache_struct(fmt);
-    if (s_object == NULL) {
-        Py_DECREF(newargs);
-        return NULL;
-    }
-    result = s_pack_into(s_object, newargs);
-    Py_DECREF(newargs);
-    Py_DECREF(s_object);
-    return result;
-}
-
-PyDoc_STRVAR(unpack_doc,
-"unpack(fmt, buffer) -> (v1, v2, ...)\n\
-\n\
-Return a tuple containing values unpacked according to the format string\n\
-fmt.  Requires len(buffer) == calcsize(fmt). See help(struct) for more\n\
-on format strings.");
-
-static PyObject *
-unpack(PyObject *self, PyObject *args)
-{
-    PyObject *s_object, *fmt, *inputstr, *result;
-
-    if (!PyArg_UnpackTuple(args, "unpack", 2, 2, &fmt, &inputstr))
-        return NULL;
-
-    s_object = cache_struct(fmt);
-    if (s_object == NULL)
-        return NULL;
-    result = s_unpack(s_object, inputstr);
-    Py_DECREF(s_object);
-    return result;
-}
-
-PyDoc_STRVAR(unpack_from_doc,
-"unpack_from(fmt, buffer, offset=0) -> (v1, v2, ...)\n\
-\n\
-Return a tuple containing values unpacked according to the format string\n\
-fmt.  Requires len(buffer[offset:]) >= calcsize(fmt).  See help(struct)\n\
-for more on format strings.");
-
-static PyObject *
-unpack_from(PyObject *self, PyObject *args, PyObject *kwds)
-{
-    PyObject *s_object, *fmt, *newargs, *result;
-    Py_ssize_t n = PyTuple_GET_SIZE(args);
-
-    if (n == 0) {
-        PyErr_SetString(PyExc_TypeError, "missing format argument");
-        return NULL;
-    }
-    fmt = PyTuple_GET_ITEM(args, 0);
-    newargs = PyTuple_GetSlice(args, 1, n);
-    if (newargs == NULL)
-        return NULL;
-
-    s_object = cache_struct(fmt);
-    if (s_object == NULL) {
-        Py_DECREF(newargs);
-        return NULL;
-    }
-    result = s_unpack_from(s_object, newargs, kwds);
-    Py_DECREF(newargs);
-    Py_DECREF(s_object);
-    return result;
-}
-
-static struct PyMethodDef module_functions[] = {
-    {"_clearcache",     (PyCFunction)clearcache,        METH_NOARGS,    clearcache_doc},
-    {"calcsize",        calcsize,       METH_O, calcsize_doc},
-    {"pack",            pack,           METH_VARARGS,   pack_doc},
-    {"pack_into",       pack_into,      METH_VARARGS,   pack_into_doc},
-    {"unpack",          unpack, METH_VARARGS,   unpack_doc},
-    {"unpack_from",     (PyCFunction)unpack_from,
-                    METH_VARARGS|METH_KEYWORDS,         unpack_from_doc},
-    {NULL,       NULL}          /* sentinel */
-};
-
-
-/* Module initialization */
-
-PyDoc_STRVAR(module_doc,
-"Functions to convert between Python values and C structs.\n\
-Python bytes objects are used to hold the data representing the C struct\n\
-and also as format strings (explained below) to describe the layout of data\n\
-in the C struct.\n\
-\n\
-The optional first format char indicates byte order, size and alignment:\n\
-  @: native order, size & alignment (default)\n\
-  =: native order, std. size & alignment\n\
-  <: little-endian, std. size & alignment\n\
-  >: big-endian, std. size & alignment\n\
-  !: same as >\n\
-\n\
-The remaining chars indicate types of args and must match exactly;\n\
-these can be preceded by a decimal repeat count:\n\
-  x: pad byte (no data); c:char; b:signed byte; B:unsigned byte;\n\
-  ?: _Bool (requires C99; if not available, char is used instead)\n\
-  h:short; H:unsigned short; i:int; I:unsigned int;\n\
-  l:long; L:unsigned long; f:float; d:double.\n\
-Special cases (preceding decimal count indicates length):\n\
-  s:string (array of char); p: pascal string (with count byte).\n\
-Special cases (only available in native format):\n\
-  n:ssize_t; N:size_t;\n\
-  P:an integer type that is wide enough to hold a pointer.\n\
-Special case (not in native mode unless 'long long' in platform C):\n\
-  q:long long; Q:unsigned long long\n\
-Whitespace between formats is ignored.\n\
-\n\
-The variable struct.error is an exception raised on errors.\n");
-
-
-static struct PyModuleDef _structmodule = {
-    PyModuleDef_HEAD_INIT,
-    "_struct",
-    module_doc,
-    -1,
-    module_functions,
-    NULL,
-    NULL,
-    NULL,
-    NULL
-};
-
-extern "C"
-PyMODINIT_FUNC
-PyInit__pvt_struct(void)
-{
-    PyObject *m;
-
-    m = PyModule_Create(&_structmodule);
-    if (m == NULL)
-        return NULL;
-
-    Py_TYPE(&PyStructType) = &PyType_Type;
-    if (PyType_Ready(&PyStructType) < 0)
-        return NULL;
-
-    /* Add some symbolic constants to the module */
-    if (StructError == NULL) {
-        StructError = PyErr_NewException("struct.error", NULL, NULL);
-        if (StructError == NULL)
-            return NULL;
-    }
-
-    Py_INCREF(StructError);
-    PyModule_AddObject(m, "error", StructError);
-
-    Py_INCREF((PyObject*)&PyStructType);
-    PyModule_AddObject(m, "Struct", (PyObject*)&PyStructType);
-
-    return m;
-}
-
-// vim: fdm=marker
diff --git a/src/wrapper/bitlog.cpp b/src/wrapper/bitlog.cpp
deleted file mode 100644
index 88b820fa..00000000
--- a/src/wrapper/bitlog.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-#include "bitlog.hpp"
-
-
-
-
-/* from http://graphics.stanford.edu/~seander/bithacks.html */
-const char pyopencl::log_table_8[] =
-{
-  0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
-  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
-};
-
-
diff --git a/src/wrapper/bitlog.hpp b/src/wrapper/bitlog.hpp
deleted file mode 100644
index 405599e7..00000000
--- a/src/wrapper/bitlog.hpp
+++ /dev/null
@@ -1,53 +0,0 @@
-// Base-2 logarithm bithack.
-
-
-
-
-#ifndef _AFJDFJSDFSD_PYOPENCL_HEADER_SEEN_BITLOG_HPP
-#define _AFJDFJSDFSD_PYOPENCL_HEADER_SEEN_BITLOG_HPP
-
-
-
-
-#include <climits>
-#include <boost/cstdint.hpp>
-
-
-
-
-namespace pyopencl
-{
-  extern const char log_table_8[];
-
-  inline unsigned bitlog2_16(boost::uint16_t v)
-  {
-    if (unsigned long t = v >> 8)
-      return 8+log_table_8[t];
-    else 
-      return log_table_8[v];
-  }
-
-  inline unsigned bitlog2_32(boost::uint32_t v)
-  {
-    if (boost::uint16_t t = v >> 16)
-      return 16+bitlog2_16(t);
-    else 
-      return bitlog2_16(v);
-  }
-
-  inline unsigned bitlog2(unsigned long v)
-  {
-#if (ULONG_MAX != 4294967295)
-    if (boost::uint32_t t = v >> 32)
-      return 32+bitlog2_32(t);
-    else 
-#endif
-      return bitlog2_32(v);
-  }
-}
-
-
-
-
-
-#endif
diff --git a/src/wrapper/mempool.hpp b/src/wrapper/mempool.hpp
deleted file mode 100644
index be88f13f..00000000
--- a/src/wrapper/mempool.hpp
+++ /dev/null
@@ -1,376 +0,0 @@
-// Abstract memory pool implementation
-
-
-
-
-#ifndef _AFJDFJSDFSD_PYGPU_HEADER_SEEN_MEMPOOL_HPP
-#define _AFJDFJSDFSD_PYGPU_HEADER_SEEN_MEMPOOL_HPP
-
-
-
-
-#include <boost/ptr_container/ptr_map.hpp>
-#include <boost/foreach.hpp>
-#include <boost/format.hpp>
-#include "bitlog.hpp"
-
-
-
-
-namespace PYGPU_PACKAGE
-{
-  template <class T>
-  inline T signed_left_shift(T x, signed shift_amount)
-  {
-    if (shift_amount < 0)
-      return x >> -shift_amount;
-    else
-      return x << shift_amount;
-  }
-
-
-
-
-  template <class T>
-  inline T signed_right_shift(T x, signed shift_amount)
-  {
-    if (shift_amount < 0)
-      return x << -shift_amount;
-    else
-      return x >> shift_amount;
-  }
-
-
-
-
-  template<class Allocator>
-  class memory_pool
-  {
-    public:
-      typedef typename Allocator::pointer_type pointer_type;
-      typedef typename Allocator::size_type size_type;
-
-    private:
-      typedef boost::uint32_t bin_nr_t;
-      typedef std::vector<pointer_type> bin_t;
-
-      typedef boost::ptr_map<bin_nr_t, bin_t > container_t;
-      container_t m_container;
-      typedef typename container_t::value_type bin_pair_t;
-
-      std::auto_ptr<Allocator> m_allocator;
-
-      // A held block is one that's been released by the application, but that
-      // we are keeping around to dish out again.
-      unsigned m_held_blocks;
-
-      // An active block is one that is in use by the application.
-      unsigned m_active_blocks;
-
-      bool m_stop_holding;
-      int m_trace;
-
-    public:
-      memory_pool(Allocator const &alloc=Allocator())
-        : m_allocator(alloc.copy()),
-        m_held_blocks(0), m_active_blocks(0), m_stop_holding(false),
-        m_trace(false)
-      {
-        if (m_allocator->is_deferred())
-        {
-          PyErr_WarnEx(PyExc_UserWarning, "Memory pools expect non-deferred "
-              "semantics from their allocators. You passed a deferred "
-              "allocator, i.e. an allocator whose allocations can turn out to "
-              "be unavailable long after allocation.", 1);
-        }
-      }
-
-      virtual ~memory_pool()
-      { free_held(); }
-
-      static const unsigned mantissa_bits = 2;
-      static const unsigned mantissa_mask = (1 << mantissa_bits) - 1;
-
-      static bin_nr_t bin_number(size_type size)
-      {
-        signed l = bitlog2(size);
-        size_type shifted = signed_right_shift(size, l-signed(mantissa_bits));
-        if (size && (shifted & (1 << mantissa_bits)) == 0)
-          throw std::runtime_error("memory_pool::bin_number: bitlog2 fault");
-        size_type chopped = shifted & mantissa_mask;
-        return l << mantissa_bits | chopped;
-      }
-
-      void set_trace(bool flag)
-      {
-        if (flag)
-          ++m_trace;
-        else
-          --m_trace;
-      }
-
-      static size_type alloc_size(bin_nr_t bin)
-      {
-        bin_nr_t exponent = bin >> mantissa_bits;
-        bin_nr_t mantissa = bin & mantissa_mask;
-
-        size_type ones = signed_left_shift(1,
-            signed(exponent)-signed(mantissa_bits)
-            );
-        if (ones) ones -= 1;
-
-        size_type head = signed_left_shift(
-           (1<<mantissa_bits) | mantissa,
-            signed(exponent)-signed(mantissa_bits));
-        if (ones & head)
-          throw std::runtime_error("memory_pool::alloc_size: bit-counting fault");
-        return head | ones;
-      }
-
-    protected:
-      bin_t &get_bin(bin_nr_t bin_nr)
-      {
-        typename container_t::iterator it = m_container.find(bin_nr);
-        if (it == m_container.end())
-        {
-          bin_t *new_bin = new bin_t;
-          m_container.insert(bin_nr, new_bin);
-          return *new_bin;
-        }
-        else
-          return *it->second;
-      }
-
-      void inc_held_blocks()
-      {
-        if (m_held_blocks == 0)
-          start_holding_blocks();
-        ++m_held_blocks;
-      }
-
-      void dec_held_blocks()
-      {
-        --m_held_blocks;
-        if (m_held_blocks == 0)
-          stop_holding_blocks();
-      }
-
-      virtual void start_holding_blocks()
-      { }
-
-      virtual void stop_holding_blocks()
-      { }
-
-    public:
-      pointer_type allocate(size_type size)
-      {
-        bin_nr_t bin_nr = bin_number(size);
-        bin_t &bin = get_bin(bin_nr);
-
-        if (bin.size())
-        {
-          if (m_trace)
-            std::cout
-              << "[pool] allocation of size " << size << " served from bin " << bin_nr
-              << " which contained " << bin.size() << " entries" << std::endl;
-          return pop_block_from_bin(bin, size);
-        }
-
-        size_type alloc_sz = alloc_size(bin_nr);
-
-        assert(bin_number(alloc_sz) == bin_nr);
-
-        if (m_trace)
-          std::cout << "[pool] allocation of size " << size << " required new memory" << std::endl;
-
-        try { return get_from_allocator(alloc_sz); }
-        catch (PYGPU_PACKAGE::error &e)
-        {
-          if (!e.is_out_of_memory())
-            throw;
-        }
-
-        if (m_trace)
-          std::cout << "[pool] allocation triggered OOM, running GC" << std::endl;
-
-        m_allocator->try_release_blocks();
-        if (bin.size())
-          return pop_block_from_bin(bin, size);
-
-        if (m_trace)
-          std::cout << "[pool] allocation still OOM after GC" << std::endl;
-
-        while (try_to_free_memory())
-        {
-          try { return get_from_allocator(alloc_sz); }
-          catch (PYGPU_PACKAGE::error &e)
-          {
-            if (!e.is_out_of_memory())
-              throw;
-          }
-        }
-
-        throw PYGPU_PACKAGE::error(
-            "memory_pool::allocate",
-#ifdef PYGPU_PYCUDA
-            CUDA_ERROR_OUT_OF_MEMORY,
-#endif
-#ifdef PYGPU_PYOPENCL
-            CL_MEM_OBJECT_ALLOCATION_FAILURE,
-#endif
-            "failed to free memory for allocation");
-      }
-
-      void free(pointer_type p, size_type size)
-      {
-        --m_active_blocks;
-        bin_nr_t bin_nr = bin_number(size);
-
-        if (!m_stop_holding)
-        {
-          inc_held_blocks();
-          get_bin(bin_nr).push_back(p);
-
-          if (m_trace)
-            std::cout << "[pool] block of size " << size << " returned to bin "
-              << bin_nr << " which now contains " << get_bin(bin_nr).size()
-              << " entries" << std::endl;
-        }
-        else
-          m_allocator->free(p);
-      }
-
-      void free_held()
-      {
-        BOOST_FOREACH(bin_pair_t bin_pair, m_container)
-        {
-          bin_t &bin = *bin_pair.second;
-
-          while (bin.size())
-          {
-            m_allocator->free(bin.back());
-            bin.pop_back();
-
-            dec_held_blocks();
-          }
-        }
-
-        assert(m_held_blocks == 0);
-      }
-
-      void stop_holding()
-      {
-        m_stop_holding = true;
-        free_held();
-      }
-
-      unsigned active_blocks()
-      { return m_active_blocks; }
-
-      unsigned held_blocks()
-      { return m_held_blocks; }
-
-      bool try_to_free_memory()
-      {
-        BOOST_FOREACH(bin_pair_t bin_pair,
-            // free largest stuff first
-            std::make_pair(m_container.rbegin(), m_container.rend()))
-        {
-          bin_t &bin = *bin_pair.second;
-
-          if (bin.size())
-          {
-            m_allocator->free(bin.back());
-            bin.pop_back();
-
-            dec_held_blocks();
-
-            return true;
-          }
-        }
-
-        return false;
-      }
-
-    private:
-      pointer_type get_from_allocator(size_type alloc_sz)
-      {
-        pointer_type result = m_allocator->allocate(alloc_sz);
-        ++m_active_blocks;
-
-        return result;
-      }
-
-      pointer_type pop_block_from_bin(bin_t &bin, size_type size)
-      {
-        pointer_type result = bin.back();
-        bin.pop_back();
-
-        dec_held_blocks();
-        ++m_active_blocks;
-
-        return result;
-      }
-  };
-
-
-
-
-
-  template <class Pool>
-  class pooled_allocation : public boost::noncopyable
-  {
-    public:
-      typedef Pool pool_type;
-      typedef typename Pool::pointer_type pointer_type;
-      typedef typename Pool::size_type size_type;
-
-    private:
-      boost::shared_ptr<pool_type> m_pool;
-
-      pointer_type m_ptr;
-      size_type m_size;
-      bool m_valid;
-
-    public:
-      pooled_allocation(boost::shared_ptr<pool_type> p, size_type size)
-        : m_pool(p), m_ptr(p->allocate(size)), m_size(size), m_valid(true)
-      { }
-
-      ~pooled_allocation()
-      {
-        if (m_valid)
-          free();
-      }
-
-      void free()
-      {
-        if (m_valid)
-        {
-          m_pool->free(m_ptr, m_size);
-          m_valid = false;
-        }
-        else
-          throw PYGPU_PACKAGE::error(
-              "pooled_device_allocation::free", 
-#ifdef PYGPU_PYCUDA
-              CUDA_ERROR_INVALID_HANDLE
-#endif
-#ifdef PYGPU_PYOPENCL
-              CL_INVALID_VALUE
-#endif
-              );
-      }
-
-      pointer_type ptr() const
-      { return m_ptr; }
-
-      size_type size() const
-      { return m_size; }
-  };
-}
-
-
-
-
-#endif
diff --git a/src/wrapper/numpy_init.hpp b/src/wrapper/numpy_init.hpp
deleted file mode 100644
index 9d34ac57..00000000
--- a/src/wrapper/numpy_init.hpp
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef _FAYHVVAAA_PYOPENCL_HEADER_SEEN_NUMPY_INIT_HPP
-#define _FAYHVVAAA_PYOPENCL_HEADER_SEEN_NUMPY_INIT_HPP
-
-
-
-
-#include <numpy/arrayobject.h>
-#include <stdexcept>
-
-
-
-
-namespace
-{
-  static struct pyublas_array_importer
-  {
-    static bool do_import_array()
-    {
-      import_array1(false);
-      return true;
-    }
-
-    pyublas_array_importer()
-    {
-      if (!do_import_array())
-        throw std::runtime_error("numpy failed to initialize");
-    }
-  } _array_importer;
-}
-
-
-
-
-#endif
diff --git a/src/wrapper/tools.hpp b/src/wrapper/tools.hpp
deleted file mode 100644
index 7254ace1..00000000
--- a/src/wrapper/tools.hpp
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef _ASDFDAFVVAFF_PYCUDA_HEADER_SEEN_TOOLS_HPP
-#define _ASDFDAFVVAFF_PYCUDA_HEADER_SEEN_TOOLS_HPP
-
-
-
-
-#include <boost/python.hpp>
-#include <numeric>
-#include "numpy_init.hpp"
-
-
-
-
-namespace pyopencl
-{
-  inline
-  npy_intp size_from_dims(int ndim, const npy_intp *dims)
-  {
-    if (ndim != 0)
-      return std::accumulate(dims, dims+ndim, 1, std::multiplies<npy_intp>());
-    else
-      return 1;
-  }
-
-
-
-
-  inline void run_python_gc()
-  {
-    namespace py = boost::python;
-
-    py::object gc_mod(
-        py::handle<>(
-          PyImport_ImportModule("gc")));
-    gc_mod.attr("collect")();
-  }
-}
-
-
-
-
-
-#endif
diff --git a/src/wrapper/wrap_cl.cpp b/src/wrapper/wrap_cl.cpp
deleted file mode 100644
index 9f680f2d..00000000
--- a/src/wrapper/wrap_cl.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#include "wrap_cl.hpp"
-
-
-
-
-using namespace pyopencl;
-
-
-
-
-extern void pyopencl_expose_constants();
-extern void pyopencl_expose_part_1();
-extern void pyopencl_expose_part_2();
-extern void pyopencl_expose_mempool();
-
-BOOST_PYTHON_MODULE(_cl)
-{
-  pyopencl_expose_constants();
-  pyopencl_expose_part_1();
-  pyopencl_expose_part_2();
-  pyopencl_expose_mempool();
-}
-
-// vim: foldmethod=marker
diff --git a/src/wrapper/wrap_cl.hpp b/src/wrapper/wrap_cl.hpp
deleted file mode 100644
index cce59d66..00000000
--- a/src/wrapper/wrap_cl.hpp
+++ /dev/null
@@ -1,4013 +0,0 @@
-#ifndef _AFJHAYYTA_PYOPENCL_HEADER_SEEN_WRAP_CL_HPP
-#define _AFJHAYYTA_PYOPENCL_HEADER_SEEN_WRAP_CL_HPP
-
-// CL 1.2 undecided:
-// clSetPrintfCallback
-
-// {{{ includes
-
-#define CL_USE_DEPRECATED_OPENCL_1_1_APIS
-
-#ifdef __APPLE__
-
-// Mac ------------------------------------------------------------------------
-#include <OpenCL/opencl.h>
-#ifdef HAVE_GL
-
-#define PYOPENCL_GL_SHARING_VERSION 1
-
-#include <OpenGL/OpenGL.h>
-#include <OpenCL/cl_gl.h>
-#include <OpenCL/cl_gl_ext.h>
-#endif
-
-#else
-
-// elsewhere ------------------------------------------------------------------
-#include <CL/cl.h>
-#include <CL/cl_ext.h>
-
-#if defined(_WIN32)
-#define NOMINMAX
-#include <windows.h>
-#endif
-
-#ifdef HAVE_GL
-#include <GL/gl.h>
-#include <CL/cl_gl.h>
-#endif
-
-#if defined(cl_khr_gl_sharing) && (cl_khr_gl_sharing >= 1)
-#define PYOPENCL_GL_SHARING_VERSION cl_khr_gl_sharing
-#endif
-
-#endif
-
-#include <stdexcept>
-#include <iostream>
-#include <vector>
-#include <utility>
-#include <numeric>
-#include <boost/python/slice.hpp>
-#include <boost/foreach.hpp>
-#include <boost/scoped_array.hpp>
-#include "wrap_helpers.hpp"
-#include "numpy_init.hpp"
-#include "tools.hpp"
-
-#ifdef PYOPENCL_PRETEND_CL_VERSION
-#define PYOPENCL_CL_VERSION PYOPENCL_PRETEND_CL_VERSION
-#else
-
-#if defined(CL_VERSION_1_2)
-#define PYOPENCL_CL_VERSION 0x1020
-#elif defined(CL_VERSION_1_1)
-#define PYOPENCL_CL_VERSION 0x1010
-#else
-#define PYOPENCL_CL_VERSION 0x1000
-#endif
-
-#endif
-
-// }}}
-
-
-
-
-
-// {{{ tools
-#if PY_VERSION_HEX >= 0x02050000
-  typedef Py_ssize_t PYOPENCL_BUFFER_SIZE_T;
-#else
-  typedef int PYOPENCL_BUFFER_SIZE_T;
-#endif
-
-#define PYOPENCL_CAST_BOOL(B) ((B) ? CL_TRUE : CL_FALSE)
-
-
-
-
-
-#define PYOPENCL_DEPRECATED(WHAT, KILL_VERSION, EXTRA_MSG) \
-  { \
-    PyErr_Warn( \
-        PyExc_DeprecationWarning, \
-        WHAT " is deprecated and will stop working in PyOpenCL " KILL_VERSION". " \
-        EXTRA_MSG); \
-  }
-
-#if PYOPENCL_CL_VERSION >= 0x1020
-
-#define PYOPENCL_GET_EXT_FUN(PLATFORM, NAME, VAR) \
-    NAME##_fn VAR \
-      = (NAME##_fn) \
-      clGetExtensionFunctionAddressForPlatform(PLATFORM, #NAME); \
-    \
-    if (!VAR) \
-      throw error(#NAME, CL_INVALID_VALUE, #NAME \
-          "not available");
-
-#else
-
-#define PYOPENCL_GET_EXT_FUN(PLATFORM, NAME, VAR) \
-    NAME##_fn VAR \
-      = (NAME##_fn) \
-      clGetExtensionFunctionAddress(#NAME); \
-    \
-    if (!VAR) \
-      throw error(#NAME, CL_INVALID_VALUE, #NAME \
-          "not available");
-
-#endif
-
-
-#define PYOPENCL_PARSE_PY_DEVICES \
-    std::vector<cl_device_id> devices_vec; \
-    cl_uint num_devices; \
-    cl_device_id *devices; \
-    \
-    if (py_devices.ptr() == Py_None) \
-    { \
-      num_devices = 0; \
-      devices = 0; \
-    } \
-    else \
-    { \
-      PYTHON_FOREACH(py_dev, py_devices) \
-        devices_vec.push_back( \
-            py::extract<device &>(py_dev)().data()); \
-      num_devices = devices_vec.size(); \
-      devices = devices_vec.empty( ) ? NULL : &devices_vec.front(); \
-    } \
-
-
-#define PYOPENCL_RETRY_RETURN_IF_MEM_ERROR(OPERATION) \
-    try \
-    { \
-      OPERATION \
-    } \
-    catch (pyopencl::error &e) \
-    { \
-      if (!e.is_out_of_memory()) \
-        throw; \
-    } \
-    \
-    /* If we get here, we got an error from CL.
-     * We should run the Python GC to try and free up
-     * some memory references. */ \
-    run_python_gc(); \
-    \
-    /* Now retry the allocation. If it fails again,
-     * let it fail. */ \
-    { \
-      OPERATION \
-    }
-
-
-
-
-#define PYOPENCL_RETRY_IF_MEM_ERROR(OPERATION) \
-  { \
-    bool failed_with_mem_error = false; \
-    try \
-    { \
-      OPERATION \
-    } \
-    catch (pyopencl::error &e) \
-    { \
-      failed_with_mem_error = true; \
-      if (!e.is_out_of_memory()) \
-        throw; \
-    } \
-    \
-    if (failed_with_mem_error) \
-    { \
-      /* If we get here, we got an error from CL.
-       * We should run the Python GC to try and free up
-       * some memory references. */ \
-      run_python_gc(); \
-      \
-      /* Now retry the allocation. If it fails again,
-       * let it fail. */ \
-      { \
-        OPERATION \
-      } \
-    } \
-  }
-
-// }}}
-
-// {{{ tracing and error reporting
-#ifdef PYOPENCL_TRACE
-  #define PYOPENCL_PRINT_CALL_TRACE(NAME) \
-    std::cerr << NAME << std::endl;
-  #define PYOPENCL_PRINT_CALL_TRACE_INFO(NAME, EXTRA_INFO) \
-    std::cerr << NAME << " (" << EXTRA_INFO << ')' << std::endl;
-#else
-  #define PYOPENCL_PRINT_CALL_TRACE(NAME) /*nothing*/
-  #define PYOPENCL_PRINT_CALL_TRACE_INFO(NAME, EXTRA_INFO) /*nothing*/
-#endif
-
-#define PYOPENCL_CALL_GUARDED_THREADED_WITH_TRACE_INFO(NAME, ARGLIST, TRACE_INFO) \
-  { \
-    PYOPENCL_PRINT_CALL_TRACE_INFO(#NAME, TRACE_INFO); \
-    cl_int status_code; \
-    Py_BEGIN_ALLOW_THREADS \
-      status_code = NAME ARGLIST; \
-    Py_END_ALLOW_THREADS \
-    if (status_code != CL_SUCCESS) \
-      throw pyopencl::error(#NAME, status_code);\
-  }
-
-#define PYOPENCL_CALL_GUARDED_WITH_TRACE_INFO(NAME, ARGLIST, TRACE_INFO) \
-  { \
-    PYOPENCL_PRINT_CALL_TRACE_INFO(#NAME, TRACE_INFO); \
-    cl_int status_code; \
-    status_code = NAME ARGLIST; \
-    if (status_code != CL_SUCCESS) \
-      throw pyopencl::error(#NAME, status_code);\
-  }
-
-#define PYOPENCL_CALL_GUARDED_THREADED(NAME, ARGLIST) \
-  { \
-    PYOPENCL_PRINT_CALL_TRACE(#NAME); \
-    cl_int status_code; \
-    Py_BEGIN_ALLOW_THREADS \
-      status_code = NAME ARGLIST; \
-    Py_END_ALLOW_THREADS \
-    if (status_code != CL_SUCCESS) \
-      throw pyopencl::error(#NAME, status_code);\
-  }
-
-#define PYOPENCL_CALL_GUARDED(NAME, ARGLIST) \
-  { \
-    PYOPENCL_PRINT_CALL_TRACE(#NAME); \
-    cl_int status_code; \
-    status_code = NAME ARGLIST; \
-    if (status_code != CL_SUCCESS) \
-      throw pyopencl::error(#NAME, status_code);\
-  }
-#define PYOPENCL_CALL_GUARDED_CLEANUP(NAME, ARGLIST) \
-  { \
-    PYOPENCL_PRINT_CALL_TRACE(#NAME); \
-    cl_int status_code; \
-    status_code = NAME ARGLIST; \
-    if (status_code != CL_SUCCESS) \
-      std::cerr \
-        << "PyOpenCL WARNING: a clean-up operation failed (dead context maybe?)" \
-        << std::endl \
-        << #NAME " failed with code " << status_code \
-        << std::endl; \
-  }
-
-// }}}
-
-// {{{ get_info helpers
-#define PYOPENCL_GET_OPAQUE_INFO(WHAT, FIRST_ARG, SECOND_ARG, CL_TYPE, TYPE) \
-  { \
-    CL_TYPE param_value; \
-    PYOPENCL_CALL_GUARDED(clGet##WHAT##Info, \
-          (FIRST_ARG, SECOND_ARG, sizeof(param_value), &param_value, 0)); \
-    if (param_value) \
-      return py::object(handle_from_new_ptr( \
-            new TYPE(param_value, /*retain*/ true))); \
-    else \
-      return py::object(); \
-  }
-
-#define PYOPENCL_GET_VEC_INFO(WHAT, FIRST_ARG, SECOND_ARG, RES_VEC) \
-  { \
-    size_t size; \
-    PYOPENCL_CALL_GUARDED(clGet##WHAT##Info, \
-        (FIRST_ARG, SECOND_ARG, 0, 0, &size)); \
-    \
-    RES_VEC.resize(size / sizeof(RES_VEC.front())); \
-    \
-    PYOPENCL_CALL_GUARDED(clGet##WHAT##Info, \
-        (FIRST_ARG, SECOND_ARG, size, \
-         RES_VEC.empty( ) ? NULL : &RES_VEC.front(), &size)); \
-  }
-
-#define PYOPENCL_GET_STR_INFO(WHAT, FIRST_ARG, SECOND_ARG) \
-  { \
-    size_t param_value_size; \
-    PYOPENCL_CALL_GUARDED(clGet##WHAT##Info, \
-        (FIRST_ARG, SECOND_ARG, 0, 0, &param_value_size)); \
-    \
-    std::vector<char> param_value(param_value_size); \
-    PYOPENCL_CALL_GUARDED(clGet##WHAT##Info, \
-        (FIRST_ARG, SECOND_ARG, param_value_size,  \
-         param_value.empty( ) ? NULL : &param_value.front(), &param_value_size)); \
-    \
-    return py::object( \
-        param_value.empty( ) ? "" : std::string(&param_value.front(), param_value_size-1)); \
-  }
-
-
-
-
-#define PYOPENCL_GET_INTEGRAL_INFO(WHAT, FIRST_ARG, SECOND_ARG, TYPE) \
-  { \
-    TYPE param_value; \
-    PYOPENCL_CALL_GUARDED(clGet##WHAT##Info, \
-        (FIRST_ARG, SECOND_ARG, sizeof(param_value), &param_value, 0)); \
-    return py::object(param_value); \
-  }
-
-// }}}
-
-// {{{ event helpers --------------------------------------------------------------
-#define PYOPENCL_PARSE_WAIT_FOR \
-    cl_uint num_events_in_wait_list = 0; \
-    std::vector<cl_event> event_wait_list; \
-    \
-    if (py_wait_for.ptr() != Py_None) \
-    { \
-      event_wait_list.resize(len(py_wait_for)); \
-      PYTHON_FOREACH(evt, py_wait_for) \
-        event_wait_list[num_events_in_wait_list++] = \
-        py::extract<event &>(evt)().data(); \
-    }
-
-#define PYOPENCL_WAITLIST_ARGS \
-    num_events_in_wait_list, event_wait_list.empty( ) ? NULL : &event_wait_list.front()
-
-#define PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, obj) \
-    try \
-    { \
-      return new nanny_event(evt, false, obj); \
-    } \
-    catch (...) \
-    { \
-      clReleaseEvent(evt); \
-      throw; \
-    }
-
-#define PYOPENCL_RETURN_NEW_EVENT(evt) \
-    try \
-    { \
-      return new event(evt, false); \
-    } \
-    catch (...) \
-    { \
-      clReleaseEvent(evt); \
-      throw; \
-    }
-
-// }}}
-
-// {{{ equality testing
-#define PYOPENCL_EQUALITY_TESTS(cls) \
-    bool operator==(cls const &other) const \
-    { return data() == other.data(); } \
-    bool operator!=(cls const &other) const \
-    { return data() != other.data(); } \
-    long hash() const \
-    { return (long) (intptr_t) data(); }
-// }}}
-
-
-
-namespace pyopencl
-{
-  // {{{ error
-  class error : public std::runtime_error
-  {
-    private:
-      const char *m_routine;
-      cl_int m_code;
-
-    public:
-      error(const char *rout, cl_int c, const char *msg="")
-        : std::runtime_error(msg), m_routine(rout), m_code(c)
-      { }
-
-      const char *routine() const
-      {
-        return m_routine;
-      }
-
-      cl_int code() const
-      {
-        return m_code;
-      }
-
-      bool is_out_of_memory() const
-      {
-        return (code() == CL_MEM_OBJECT_ALLOCATION_FAILURE
-            || code() == CL_OUT_OF_RESOURCES
-            || code() == CL_OUT_OF_HOST_MEMORY);
-      }
-
-  };
-
-  // }}}
-
-  inline
-  py::tuple get_cl_header_version()
-  {
-    return py::make_tuple(
-        PYOPENCL_CL_VERSION >> (3*4),
-        (PYOPENCL_CL_VERSION >> (1*4)) & 0xff
-        );
-  }
-
-  // {{{ platform
-  class platform : boost::noncopyable
-  {
-    private:
-      cl_platform_id m_platform;
-
-    public:
-      platform(cl_platform_id pid)
-      : m_platform(pid)
-      { }
-
-      platform(cl_platform_id pid, bool /*retain (ignored)*/)
-      : m_platform(pid)
-      { }
-
-      cl_platform_id data() const
-      {
-        return m_platform;
-      }
-
-      PYOPENCL_EQUALITY_TESTS(platform);
-
-      py::object get_info(cl_platform_info param_name) const
-      {
-        switch (param_name)
-        {
-          case CL_PLATFORM_PROFILE:
-          case CL_PLATFORM_VERSION:
-          case CL_PLATFORM_NAME:
-          case CL_PLATFORM_VENDOR:
-#if !(defined(CL_PLATFORM_NVIDIA) && CL_PLATFORM_NVIDIA == 0x3001)
-          case CL_PLATFORM_EXTENSIONS:
-#endif
-            PYOPENCL_GET_STR_INFO(Platform, m_platform, param_name);
-
-          default:
-            throw error("Platform.get_info", CL_INVALID_VALUE);
-        }
-      }
-
-      py::list get_devices(cl_device_type devtype);
-  };
-
-
-
-
-  inline
-  py::list get_platforms()
-  {
-    cl_uint num_platforms = 0;
-    PYOPENCL_CALL_GUARDED(clGetPlatformIDs, (0, 0, &num_platforms));
-
-    std::vector<cl_platform_id> platforms(num_platforms);
-    PYOPENCL_CALL_GUARDED(clGetPlatformIDs,
-        (num_platforms, platforms.empty( ) ? NULL : &platforms.front(), &num_platforms));
-
-    py::list result;
-    BOOST_FOREACH(cl_platform_id pid, platforms)
-      result.append(handle_from_new_ptr(
-            new platform(pid)));
-
-    return result;
-  }
-
-  // }}}
-
-  // {{{ device
-  class device : boost::noncopyable
-  {
-    public:
-      enum reference_type_t {
-        REF_NOT_OWNABLE,
-        REF_FISSION_EXT,
-#if PYOPENCL_CL_VERSION >= 0x1020
-        REF_CL_1_2,
-#endif
-      };
-    private:
-      cl_device_id m_device;
-      reference_type_t m_ref_type;
-
-    public:
-      device(cl_device_id did)
-      : m_device(did), m_ref_type(REF_NOT_OWNABLE)
-      { }
-
-      device(cl_device_id did, bool retain, reference_type_t ref_type=REF_NOT_OWNABLE)
-      : m_device(did), m_ref_type(ref_type)
-      {
-        if (retain && ref_type != REF_NOT_OWNABLE)
-        {
-          if (false)
-          { }
-#if (defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION))
-          else if (ref_type == REF_FISSION_EXT)
-          {
-#if PYOPENCL_CL_VERSION >= 0x1020
-            cl_platform_id plat;
-            PYOPENCL_CALL_GUARDED(clGetDeviceInfo, (m_device, CL_DEVICE_PLATFORM,
-                  sizeof(plat), &plat, NULL));
-#endif
-
-            PYOPENCL_GET_EXT_FUN(plat,
-                clRetainDeviceEXT, retain_func);
-
-            PYOPENCL_CALL_GUARDED(retain_func, (did));
-          }
-#endif
-
-#if PYOPENCL_CL_VERSION >= 0x1020
-          else if (ref_type == REF_CL_1_2)
-          {
-            PYOPENCL_CALL_GUARDED(clRetainDevice, (did));
-          }
-#endif
-
-          else
-            throw error("Device", CL_INVALID_VALUE,
-                "cannot own references to devices when device fission or CL 1.2 is not available");
-        }
-      }
-
-      ~device()
-      {
-        if (false)
-        { }
-#if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION)
-        else if (m_ref_type == REF_FISSION_EXT)
-        {
-#if PYOPENCL_CL_VERSION >= 0x1020
-          cl_platform_id plat;
-          PYOPENCL_CALL_GUARDED(clGetDeviceInfo, (m_device, CL_DEVICE_PLATFORM,
-                sizeof(plat), &plat, NULL));
-#endif
-
-          PYOPENCL_GET_EXT_FUN(plat,
-              clReleaseDeviceEXT, release_func);
-
-          PYOPENCL_CALL_GUARDED_CLEANUP(release_func, (m_device));
-        }
-#endif
-
-#if PYOPENCL_CL_VERSION >= 0x1020
-        else if (m_ref_type == REF_CL_1_2)
-          PYOPENCL_CALL_GUARDED(clReleaseDevice, (m_device));
-#endif
-      }
-
-      cl_device_id data() const
-      {
-        return m_device;
-      }
-
-      PYOPENCL_EQUALITY_TESTS(device);
-
-      py::object get_info(cl_device_info param_name) const
-      {
-#define DEV_GET_INT_INF(TYPE) \
-        PYOPENCL_GET_INTEGRAL_INFO(Device, m_device, param_name, TYPE);
-
-        switch (param_name)
-        {
-          case CL_DEVICE_TYPE: DEV_GET_INT_INF(cl_device_type);
-          case CL_DEVICE_VENDOR_ID: DEV_GET_INT_INF(cl_uint);
-          case CL_DEVICE_MAX_COMPUTE_UNITS: DEV_GET_INT_INF(cl_uint);
-          case CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS: DEV_GET_INT_INF(cl_uint);
-          case CL_DEVICE_MAX_WORK_GROUP_SIZE: DEV_GET_INT_INF(size_t);
-
-          case CL_DEVICE_MAX_WORK_ITEM_SIZES:
-            {
-              std::vector<size_t> result;
-              PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result);
-              PYOPENCL_RETURN_VECTOR(size_t, result);
-            }
-
-          case CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR: DEV_GET_INT_INF(cl_uint);
-          case CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT: DEV_GET_INT_INF(cl_uint);
-          case CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT: DEV_GET_INT_INF(cl_uint);
-          case CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG: DEV_GET_INT_INF(cl_uint);
-          case CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT: DEV_GET_INT_INF(cl_uint);
-          case CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE: DEV_GET_INT_INF(cl_uint);
-
-          case CL_DEVICE_MAX_CLOCK_FREQUENCY: DEV_GET_INT_INF(cl_uint);
-          case CL_DEVICE_ADDRESS_BITS: DEV_GET_INT_INF(cl_uint);
-          case CL_DEVICE_MAX_READ_IMAGE_ARGS: DEV_GET_INT_INF(cl_uint);
-          case CL_DEVICE_MAX_WRITE_IMAGE_ARGS: DEV_GET_INT_INF(cl_uint);
-          case CL_DEVICE_MAX_MEM_ALLOC_SIZE: DEV_GET_INT_INF(cl_ulong);
-          case CL_DEVICE_IMAGE2D_MAX_WIDTH: DEV_GET_INT_INF(size_t);
-          case CL_DEVICE_IMAGE2D_MAX_HEIGHT: DEV_GET_INT_INF(size_t);
-          case CL_DEVICE_IMAGE3D_MAX_WIDTH: DEV_GET_INT_INF(size_t);
-          case CL_DEVICE_IMAGE3D_MAX_HEIGHT: DEV_GET_INT_INF(size_t);
-          case CL_DEVICE_IMAGE3D_MAX_DEPTH: DEV_GET_INT_INF(size_t);
-          case CL_DEVICE_IMAGE_SUPPORT: DEV_GET_INT_INF(cl_bool);
-          case CL_DEVICE_MAX_PARAMETER_SIZE: DEV_GET_INT_INF(size_t);
-          case CL_DEVICE_MAX_SAMPLERS: DEV_GET_INT_INF(cl_uint);
-          case CL_DEVICE_MEM_BASE_ADDR_ALIGN: DEV_GET_INT_INF(cl_uint);
-          case CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE: DEV_GET_INT_INF(cl_uint);
-          case CL_DEVICE_SINGLE_FP_CONFIG: DEV_GET_INT_INF(cl_device_fp_config);
-#ifdef CL_DEVICE_DOUBLE_FP_CONFIG
-          case CL_DEVICE_DOUBLE_FP_CONFIG: DEV_GET_INT_INF(cl_device_fp_config);
-#endif
-#ifdef CL_DEVICE_HALF_FP_CONFIG
-          case CL_DEVICE_HALF_FP_CONFIG: DEV_GET_INT_INF(cl_device_fp_config);
-#endif
-
-          case CL_DEVICE_GLOBAL_MEM_CACHE_TYPE: DEV_GET_INT_INF(cl_device_mem_cache_type);
-          case CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE: DEV_GET_INT_INF(cl_uint);
-          case CL_DEVICE_GLOBAL_MEM_CACHE_SIZE: DEV_GET_INT_INF(cl_ulong);
-          case CL_DEVICE_GLOBAL_MEM_SIZE: DEV_GET_INT_INF(cl_ulong);
-
-          case CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE: DEV_GET_INT_INF(cl_ulong);
-          case CL_DEVICE_MAX_CONSTANT_ARGS: DEV_GET_INT_INF(cl_uint);
-          case CL_DEVICE_LOCAL_MEM_TYPE: DEV_GET_INT_INF(cl_device_local_mem_type);
-          case CL_DEVICE_LOCAL_MEM_SIZE: DEV_GET_INT_INF(cl_ulong);
-          case CL_DEVICE_ERROR_CORRECTION_SUPPORT: DEV_GET_INT_INF(cl_bool);
-          case CL_DEVICE_PROFILING_TIMER_RESOLUTION: DEV_GET_INT_INF(size_t);
-          case CL_DEVICE_ENDIAN_LITTLE: DEV_GET_INT_INF(cl_bool);
-          case CL_DEVICE_AVAILABLE: DEV_GET_INT_INF(cl_bool);
-          case CL_DEVICE_COMPILER_AVAILABLE: DEV_GET_INT_INF(cl_bool);
-          case CL_DEVICE_EXECUTION_CAPABILITIES: DEV_GET_INT_INF(cl_device_exec_capabilities);
-          case CL_DEVICE_QUEUE_PROPERTIES: DEV_GET_INT_INF(cl_command_queue_properties);
-
-          case CL_DEVICE_NAME:
-          case CL_DEVICE_VENDOR:
-          case CL_DRIVER_VERSION:
-          case CL_DEVICE_PROFILE:
-          case CL_DEVICE_VERSION:
-          case CL_DEVICE_EXTENSIONS:
-            PYOPENCL_GET_STR_INFO(Device, m_device, param_name);
-
-          case CL_DEVICE_PLATFORM:
-            PYOPENCL_GET_OPAQUE_INFO(Device, m_device, param_name, cl_platform_id, platform);
-
-#if PYOPENCL_CL_VERSION >= 0x1010
-          case CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF: DEV_GET_INT_INF(cl_uint);
-
-          case CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR: DEV_GET_INT_INF(cl_uint);
-          case CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT: DEV_GET_INT_INF(cl_uint);
-          case CL_DEVICE_NATIVE_VECTOR_WIDTH_INT: DEV_GET_INT_INF(cl_uint);
-          case CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG: DEV_GET_INT_INF(cl_uint);
-          case CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT: DEV_GET_INT_INF(cl_uint);
-          case CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE: DEV_GET_INT_INF(cl_uint);
-          case CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF: DEV_GET_INT_INF(cl_uint);
-
-          case CL_DEVICE_HOST_UNIFIED_MEMORY: DEV_GET_INT_INF(cl_bool);
-          case CL_DEVICE_OPENCL_C_VERSION:
-            PYOPENCL_GET_STR_INFO(Device, m_device, param_name);
-#endif
-#ifdef CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV
-          case CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV:
-          case CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV:
-          case CL_DEVICE_REGISTERS_PER_BLOCK_NV:
-          case CL_DEVICE_WARP_SIZE_NV:
-            DEV_GET_INT_INF(cl_uint);
-          case CL_DEVICE_GPU_OVERLAP_NV:
-          case CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV:
-          case CL_DEVICE_INTEGRATED_MEMORY_NV:
-            DEV_GET_INT_INF(cl_bool);
-#endif
-#if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION)
-          case CL_DEVICE_PARENT_DEVICE_EXT:
-            PYOPENCL_GET_OPAQUE_INFO(Device, m_device, param_name, cl_device_id, device);
-          case CL_DEVICE_PARTITION_TYPES_EXT:
-          case CL_DEVICE_AFFINITY_DOMAINS_EXT:
-          case CL_DEVICE_PARTITION_STYLE_EXT:
-            {
-              std::vector<cl_device_partition_property_ext> result;
-              PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result);
-              PYOPENCL_RETURN_VECTOR(cl_device_partition_property_ext, result);
-            }
-          case CL_DEVICE_REFERENCE_COUNT_EXT: DEV_GET_INT_INF(cl_uint);
-#endif
-#if PYOPENCL_CL_VERSION >= 0x1020
-          case CL_DEVICE_LINKER_AVAILABLE: DEV_GET_INT_INF(cl_bool);
-          case CL_DEVICE_BUILT_IN_KERNELS:
-            PYOPENCL_GET_STR_INFO(Device, m_device, param_name);
-          case CL_DEVICE_IMAGE_MAX_BUFFER_SIZE: DEV_GET_INT_INF(size_t);
-          case CL_DEVICE_IMAGE_MAX_ARRAY_SIZE: DEV_GET_INT_INF(size_t);
-          case CL_DEVICE_PARENT_DEVICE:
-            PYOPENCL_GET_OPAQUE_INFO(Device, m_device, param_name, cl_device_id, device);
-          case CL_DEVICE_PARTITION_MAX_SUB_DEVICES: DEV_GET_INT_INF(cl_uint);
-          case CL_DEVICE_PARTITION_TYPE:
-          case CL_DEVICE_PARTITION_PROPERTIES:
-            {
-              std::vector<cl_device_partition_property> result;
-              PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result);
-              PYOPENCL_RETURN_VECTOR(cl_device_partition_property, result);
-            }
-          case CL_DEVICE_PARTITION_AFFINITY_DOMAIN:
-            {
-              std::vector<cl_device_affinity_domain> result;
-              PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result);
-              PYOPENCL_RETURN_VECTOR(cl_device_affinity_domain, result);
-            }
-          case CL_DEVICE_REFERENCE_COUNT: DEV_GET_INT_INF(cl_uint);
-          case CL_DEVICE_PREFERRED_INTEROP_USER_SYNC: DEV_GET_INT_INF(cl_bool);
-          case CL_DEVICE_PRINTF_BUFFER_SIZE: DEV_GET_INT_INF(cl_bool);
-#endif
-// {{{ AMD dev attrs
-//
-// types of AMD dev attrs divined from
-// https://www.khronos.org/registry/cl/api/1.2/cl.hpp
-#ifdef CL_DEVICE_PROFILING_TIMER_OFFSET_AMD
-          case CL_DEVICE_PROFILING_TIMER_OFFSET_AMD: DEV_GET_INT_INF(cl_ulong);
-#endif
-/* FIXME
-#ifdef CL_DEVICE_TOPOLOGY_AMD
-          case CL_DEVICE_TOPOLOGY_AMD:
-#endif
-*/
-#ifdef CL_DEVICE_BOARD_NAME_AMD
-          case CL_DEVICE_BOARD_NAME_AMD: ;
-            PYOPENCL_GET_STR_INFO(Device, m_device, param_name);
-#endif
-#ifdef CL_DEVICE_GLOBAL_FREE_MEMORY_AMD
-          case CL_DEVICE_GLOBAL_FREE_MEMORY_AMD:
-            {
-              std::vector<size_t> result;
-              PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result);
-              PYOPENCL_RETURN_VECTOR(size_t, result);
-            }
-#endif
-#ifdef CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD
-          case CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD: DEV_GET_INT_INF(cl_uint);
-#endif
-#ifdef CL_DEVICE_SIMD_WIDTH_AMD
-          case CL_DEVICE_SIMD_WIDTH_AMD: DEV_GET_INT_INF(cl_uint);
-#endif
-#ifdef CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD
-          case CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD: DEV_GET_INT_INF(cl_uint);
-#endif
-#ifdef CL_DEVICE_WAVEFRONT_WIDTH_AMD
-          case CL_DEVICE_WAVEFRONT_WIDTH_AMD: DEV_GET_INT_INF(cl_uint);
-#endif
-#ifdef CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD
-          case CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD: DEV_GET_INT_INF(cl_uint);
-#endif
-#ifdef CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD
-          case CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD: DEV_GET_INT_INF(cl_uint);
-#endif
-#ifdef CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD
-          case CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD: DEV_GET_INT_INF(cl_uint);
-#endif
-#ifdef CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD
-          case CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD: DEV_GET_INT_INF(cl_uint);
-#endif
-#ifdef CL_DEVICE_LOCAL_MEM_BANKS_AMD
-          case CL_DEVICE_LOCAL_MEM_BANKS_AMD: DEV_GET_INT_INF(cl_uint);
-#endif
-// }}}
-
-#ifdef CL_DEVICE_MAX_ATOMIC_COUNTERS_EXT
-          case CL_DEVICE_MAX_ATOMIC_COUNTERS_EXT: DEV_GET_INT_INF(cl_uint);
-#endif
-
-          default:
-            throw error("Device.get_info", CL_INVALID_VALUE);
-        }
-      }
-
-#if PYOPENCL_CL_VERSION >= 0x1020
-      py::list create_sub_devices(py::object py_properties)
-      {
-        std::vector<cl_device_partition_property> properties;
-
-        COPY_PY_LIST(cl_device_partition_property, properties);
-        properties.push_back(0);
-
-        cl_device_partition_property *props_ptr
-          = properties.empty( ) ? NULL : &properties.front();
-
-        cl_uint num_entries;
-        PYOPENCL_CALL_GUARDED(clCreateSubDevices,
-            (m_device, props_ptr, 0, NULL, &num_entries));
-
-        std::vector<cl_device_id> result;
-        result.resize(num_entries);
-
-        PYOPENCL_CALL_GUARDED(clCreateSubDevices,
-            (m_device, props_ptr, num_entries, &result.front(), NULL));
-
-        py::list py_result;
-        BOOST_FOREACH(cl_device_id did, result)
-          py_result.append(handle_from_new_ptr(
-                new pyopencl::device(did, /*retain*/true,
-                  device::REF_CL_1_2)));
-        return py_result;
-      }
-#endif
-
-#if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION)
-      py::list create_sub_devices_ext(py::object py_properties)
-      {
-        std::vector<cl_device_partition_property_ext> properties;
-
-#if PYOPENCL_CL_VERSION >= 0x1020
-        cl_platform_id plat;
-        PYOPENCL_CALL_GUARDED(clGetDeviceInfo, (m_device, CL_DEVICE_PLATFORM,
-              sizeof(plat), &plat, NULL));
-#endif
-
-        PYOPENCL_GET_EXT_FUN(plat, clCreateSubDevicesEXT, create_sub_dev);
-
-        COPY_PY_LIST(cl_device_partition_property_ext, properties);
-        properties.push_back(CL_PROPERTIES_LIST_END_EXT);
-
-        cl_device_partition_property_ext *props_ptr
-          = properties.empty( ) ? NULL : &properties.front();
-
-        cl_uint num_entries;
-        PYOPENCL_CALL_GUARDED(create_sub_dev,
-            (m_device, props_ptr, 0, NULL, &num_entries));
-
-        std::vector<cl_device_id> result;
-        result.resize(num_entries);
-
-        PYOPENCL_CALL_GUARDED(create_sub_dev,
-            (m_device, props_ptr, num_entries, &result.front(), NULL));
-
-        py::list py_result;
-        BOOST_FOREACH(cl_device_id did, result)
-          py_result.append(handle_from_new_ptr(
-                new pyopencl::device(did, /*retain*/true,
-                  device::REF_FISSION_EXT)));
-        return py_result;
-      }
-#endif
-
-  };
-
-
-
-
-  inline py::list platform::get_devices(cl_device_type devtype)
-  {
-    cl_uint num_devices = 0;
-    PYOPENCL_CALL_GUARDED(clGetDeviceIDs,
-        (m_platform, devtype, 0, 0, &num_devices));
-    if (num_devices == 0)
-      return py::list();
-
-    std::vector<cl_device_id> devices(num_devices);
-    PYOPENCL_CALL_GUARDED(clGetDeviceIDs,
-        (m_platform, devtype,
-         num_devices, devices.empty( ) ? NULL : &devices.front(), &num_devices));
-
-    py::list result;
-    BOOST_FOREACH(cl_device_id did, devices)
-      result.append(handle_from_new_ptr(
-            new device(did)));
-
-    return result;
-  }
-
-  // }}}
-
-  // {{{ context
-  class context : public boost::noncopyable
-  {
-    private:
-      cl_context m_context;
-
-    public:
-      context(cl_context ctx, bool retain)
-        : m_context(ctx)
-      {
-        if (retain)
-          PYOPENCL_CALL_GUARDED(clRetainContext, (ctx));
-      }
-
-
-      ~context()
-      {
-        PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseContext,
-            (m_context));
-      }
-
-      cl_context data() const
-      {
-        return m_context;
-      }
-
-      PYOPENCL_EQUALITY_TESTS(context);
-
-      py::object get_info(cl_context_info param_name) const
-      {
-        switch (param_name)
-        {
-          case CL_CONTEXT_REFERENCE_COUNT:
-            PYOPENCL_GET_INTEGRAL_INFO(
-                Context, m_context, param_name, cl_uint);
-
-          case CL_CONTEXT_DEVICES:
-            {
-              std::vector<cl_device_id> result;
-              PYOPENCL_GET_VEC_INFO(Context, m_context, param_name, result);
-
-              py::list py_result;
-              BOOST_FOREACH(cl_device_id did, result)
-                py_result.append(handle_from_new_ptr(
-                      new pyopencl::device(did)));
-              return py_result;
-            }
-
-          case CL_CONTEXT_PROPERTIES:
-            {
-              std::vector<cl_context_properties> result;
-              PYOPENCL_GET_VEC_INFO(Context, m_context, param_name, result);
-
-              py::list py_result;
-              for (size_t i = 0; i < result.size(); i+=2)
-              {
-                cl_context_properties key = result[i];
-                py::object value;
-                switch (key)
-                {
-                  case CL_CONTEXT_PLATFORM:
-                    {
-                      value = py::object(
-                          handle_from_new_ptr(new platform(
-                            reinterpret_cast<cl_platform_id>(result[i+1]))));
-                      break;
-                    }
-
-#if defined(PYOPENCL_GL_SHARING_VERSION) && (PYOPENCL_GL_SHARING_VERSION >= 1)
-#if defined(__APPLE__) && defined(HAVE_GL)
-                  case CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE:
-#else
-                  case CL_GL_CONTEXT_KHR:
-                  case CL_EGL_DISPLAY_KHR:
-                  case CL_GLX_DISPLAY_KHR:
-                  case CL_WGL_HDC_KHR:
-                  case CL_CGL_SHAREGROUP_KHR:
-#endif
-                    value = py::object(result[i+1]);
-                    break;
-
-#endif
-                  case 0:
-                    break;
-
-                  default:
-                    throw error("Context.get_info", CL_INVALID_VALUE,
-                        "unknown context_property key encountered");
-                }
-
-                py_result.append(py::make_tuple(result[i], value));
-              }
-              return py_result;
-            }
-
-#if PYOPENCL_CL_VERSION >= 0x1010
-          case CL_CONTEXT_NUM_DEVICES:
-            PYOPENCL_GET_INTEGRAL_INFO(
-                Context, m_context, param_name, cl_uint);
-#endif
-
-          default:
-            throw error("Context.get_info", CL_INVALID_VALUE);
-        }
-      }
-  };
-
-
-
-
-  inline
-  std::vector<cl_context_properties> parse_context_properties(
-      py::object py_properties)
-  {
-    std::vector<cl_context_properties> props;
-
-    if (py_properties.ptr() != Py_None)
-    {
-      PYTHON_FOREACH(prop_tuple, py_properties)
-      {
-        if (len(prop_tuple) != 2)
-          throw error("Context", CL_INVALID_VALUE, "property tuple must have length 2");
-        cl_context_properties prop =
-            py::extract<cl_context_properties>(prop_tuple[0]);
-        props.push_back(prop);
-
-        if (prop == CL_CONTEXT_PLATFORM)
-        {
-          py::extract<const platform &> value(prop_tuple[1]);
-          props.push_back(
-              reinterpret_cast<cl_context_properties>(value().data()));
-        }
-#if defined(PYOPENCL_GL_SHARING_VERSION) && (PYOPENCL_GL_SHARING_VERSION >= 1)
-#if defined(_WIN32)
-       else if (prop == CL_WGL_HDC_KHR)
-       {
-         // size_t is a stand-in for HANDLE, hopefully has the same size.
-         size_t hnd = py::extract<size_t>(prop_tuple[1]);
-         props.push_back(hnd);
-       }
-#endif
-       else if (
-#if defined(__APPLE__) && defined(HAVE_GL)
-            prop == CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE
-#else
-            prop == CL_GL_CONTEXT_KHR
-            || prop == CL_EGL_DISPLAY_KHR
-            || prop == CL_GLX_DISPLAY_KHR
-            || prop == CL_CGL_SHAREGROUP_KHR
-#endif
-           )
-       {
-          py::object ctypes = py::import("ctypes");
-          py::object prop = prop_tuple[1], c_void_p = ctypes.attr("c_void_p");
-          py::object ptr = ctypes.attr("cast")(prop, c_void_p);
-          py::extract<cl_context_properties> value(ptr.attr("value"));
-          props.push_back(value);
-       }
-#endif
-        else
-          throw error("Context", CL_INVALID_VALUE, "invalid context property");
-      }
-      props.push_back(0);
-    }
-
-    return props;
-  }
-
-
-
-
-  inline
-  context *create_context_inner(py::object py_devices, py::object py_properties,
-      py::object py_dev_type)
-  {
-    std::vector<cl_context_properties> props
-      = parse_context_properties(py_properties);
-
-    cl_context_properties *props_ptr
-      = props.empty( ) ? NULL : &props.front();
-
-    cl_int status_code;
-
-    cl_context ctx;
-
-    // from device list
-    if (py_devices.ptr() != Py_None)
-    {
-      if (py_dev_type.ptr() != Py_None)
-        throw error("Context", CL_INVALID_VALUE,
-            "one of 'devices' or 'dev_type' must be None");
-
-      std::vector<cl_device_id> devices;
-      PYTHON_FOREACH(py_dev, py_devices)
-      {
-        py::extract<const device &> dev(py_dev);
-          devices.push_back(dev().data());
-      }
-
-      PYOPENCL_PRINT_CALL_TRACE("clCreateContext");
-      ctx = clCreateContext(
-          props_ptr,
-          devices.size(),
-          devices.empty( ) ? NULL : &devices.front(),
-          0, 0, &status_code);
-    }
-    // from dev_type
-    else
-    {
-      cl_device_type dev_type = CL_DEVICE_TYPE_DEFAULT;
-      if (py_dev_type.ptr() != Py_None)
-        dev_type = py::extract<cl_device_type>(py_dev_type)();
-
-      PYOPENCL_PRINT_CALL_TRACE("clCreateContextFromType");
-      ctx = clCreateContextFromType(props_ptr, dev_type, 0, 0, &status_code);
-    }
-
-    if (status_code != CL_SUCCESS)
-      throw pyopencl::error("Context", status_code);
-
-    try
-    {
-      return new context(ctx, false);
-    }
-    catch (...)
-    {
-      PYOPENCL_CALL_GUARDED(clReleaseContext, (ctx));
-      throw;
-    }
-  }
-
-
-
-
-  inline
-  context *create_context(py::object py_devices, py::object py_properties,
-      py::object py_dev_type)
-  {
-    PYOPENCL_RETRY_RETURN_IF_MEM_ERROR(
-      return create_context_inner(py_devices, py_properties, py_dev_type);
-    )
-  }
-
-
-
-
-
-  // }}}
-
-  // {{{ command_queue
-  class command_queue
-  {
-    private:
-      cl_command_queue m_queue;
-
-    public:
-      command_queue(cl_command_queue q, bool retain)
-        : m_queue(q)
-      {
-        if (retain)
-          PYOPENCL_CALL_GUARDED(clRetainCommandQueue, (q));
-      }
-
-      command_queue(command_queue const &src)
-        : m_queue(src.m_queue)
-      {
-        PYOPENCL_CALL_GUARDED(clRetainCommandQueue, (m_queue));
-      }
-
-      command_queue(
-          const context &ctx,
-          const device *py_dev=0,
-          cl_command_queue_properties props=0)
-      {
-        cl_device_id dev;
-        if (py_dev)
-          dev = py_dev->data();
-        else
-        {
-          std::vector<cl_device_id> devs;
-          PYOPENCL_GET_VEC_INFO(Context, ctx.data(), CL_CONTEXT_DEVICES, devs);
-          if (devs.size() == 0)
-            throw pyopencl::error("CommandQueue", CL_INVALID_VALUE,
-                "context doesn't have any devices? -- don't know which one to default to");
-          dev = devs[0];
-        }
-
-        cl_int status_code;
-        PYOPENCL_PRINT_CALL_TRACE("clCreateCommandQueue");
-        m_queue = clCreateCommandQueue(
-            ctx.data(), dev, props, &status_code);
-
-        if (status_code != CL_SUCCESS)
-          throw pyopencl::error("CommandQueue", status_code);
-      }
-
-      ~command_queue()
-      {
-        PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseCommandQueue,
-            (m_queue));
-      }
-
-      const cl_command_queue data() const
-      { return m_queue; }
-
-      PYOPENCL_EQUALITY_TESTS(command_queue);
-
-      py::object get_info(cl_command_queue_info param_name) const
-      {
-        switch (param_name)
-        {
-          case CL_QUEUE_CONTEXT:
-            PYOPENCL_GET_OPAQUE_INFO(CommandQueue, m_queue, param_name,
-                cl_context, context);
-          case CL_QUEUE_DEVICE:
-            PYOPENCL_GET_OPAQUE_INFO(CommandQueue, m_queue, param_name,
-                cl_device_id, device);
-          case CL_QUEUE_REFERENCE_COUNT:
-            PYOPENCL_GET_INTEGRAL_INFO(CommandQueue, m_queue, param_name,
-                cl_uint);
-          case CL_QUEUE_PROPERTIES:
-            PYOPENCL_GET_INTEGRAL_INFO(CommandQueue, m_queue, param_name,
-                cl_command_queue_properties);
-
-          default:
-            throw error("CommandQueue.get_info", CL_INVALID_VALUE);
-        }
-      }
-
-      std::auto_ptr<context> get_context() const
-      {
-        cl_context param_value;
-        PYOPENCL_CALL_GUARDED(clGetCommandQueueInfo,
-            (m_queue, CL_QUEUE_CONTEXT, sizeof(param_value), &param_value, 0));
-        return std::auto_ptr<context>(
-            new context(param_value, /*retain*/ true));
-      }
-
-#if PYOPENCL_CL_VERSION < 0x1010
-      cl_command_queue_properties set_property(
-          cl_command_queue_properties prop,
-          bool enable)
-      {
-        cl_command_queue_properties old_prop;
-        PYOPENCL_CALL_GUARDED(clSetCommandQueueProperty,
-            (m_queue, prop, PYOPENCL_CAST_BOOL(enable), &old_prop));
-        return old_prop;
-      }
-#endif
-
-      void flush()
-      { PYOPENCL_CALL_GUARDED(clFlush, (m_queue)); }
-      void finish()
-      { PYOPENCL_CALL_GUARDED_THREADED(clFinish, (m_queue)); }
-  };
-
-  // }}}
-
-  // {{{ event/synchronization
-  class event : boost::noncopyable
-  {
-    private:
-      cl_event m_event;
-
-    public:
-      event(cl_event event, bool retain)
-        : m_event(event)
-      {
-        if (retain)
-          PYOPENCL_CALL_GUARDED(clRetainEvent, (event));
-      }
-
-      event(event const &src)
-        : m_event(src.m_event)
-      { PYOPENCL_CALL_GUARDED(clRetainEvent, (m_event)); }
-
-      virtual ~event()
-      {
-        PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseEvent,
-            (m_event));
-      }
-
-      const cl_event data() const
-      { return m_event; }
-
-      PYOPENCL_EQUALITY_TESTS(event);
-
-      py::object get_info(cl_event_info param_name) const
-      {
-        switch (param_name)
-        {
-          case CL_EVENT_COMMAND_QUEUE:
-            PYOPENCL_GET_OPAQUE_INFO(Event, m_event, param_name,
-                cl_command_queue, command_queue);
-          case CL_EVENT_COMMAND_TYPE:
-            PYOPENCL_GET_INTEGRAL_INFO(Event, m_event, param_name,
-                cl_command_type);
-          case CL_EVENT_COMMAND_EXECUTION_STATUS:
-            PYOPENCL_GET_INTEGRAL_INFO(Event, m_event, param_name,
-                cl_int);
-          case CL_EVENT_REFERENCE_COUNT:
-            PYOPENCL_GET_INTEGRAL_INFO(Event, m_event, param_name,
-                cl_uint);
-#if PYOPENCL_CL_VERSION >= 0x1010
-          case CL_EVENT_CONTEXT:
-            PYOPENCL_GET_OPAQUE_INFO(Event, m_event, param_name,
-                cl_context, context);
-#endif
-
-          default:
-            throw error("Event.get_info", CL_INVALID_VALUE);
-        }
-      }
-
-      py::object get_profiling_info(cl_profiling_info param_name) const
-      {
-        switch (param_name)
-        {
-          case CL_PROFILING_COMMAND_QUEUED:
-          case CL_PROFILING_COMMAND_SUBMIT:
-          case CL_PROFILING_COMMAND_START:
-          case CL_PROFILING_COMMAND_END:
-            PYOPENCL_GET_INTEGRAL_INFO(EventProfiling, m_event, param_name,
-                cl_ulong);
-          default:
-            throw error("Event.get_profiling_info", CL_INVALID_VALUE);
-        }
-      }
-
-      virtual void wait()
-      {
-        PYOPENCL_CALL_GUARDED_THREADED(clWaitForEvents, (1, &m_event));
-      }
-  };
-
-  class nanny_event : public event
-  {
-    // In addition to everything an event does, the nanny event holds a reference
-    // to a Python object and waits for its own completion upon destruction.
-
-    protected:
-      py::object        m_ward;
-
-    public:
-
-      nanny_event(cl_event evt, bool retain, py::object ward)
-        : event(evt, retain), m_ward(ward)
-      { }
-
-      nanny_event(nanny_event const &src)
-        : event(src), m_ward(src.m_ward)
-      { }
-
-      ~nanny_event()
-      { wait(); }
-
-      py::object get_ward() const
-      { return m_ward; }
-
-      virtual void wait()
-      {
-        event::wait();
-        m_ward = py::object();
-      }
-  };
-
-
-
-
-  inline
-  void wait_for_events(py::object events)
-  {
-    cl_uint num_events_in_wait_list = 0;
-    std::vector<cl_event> event_wait_list(len(events));
-
-    PYTHON_FOREACH(evt, events)
-      event_wait_list[num_events_in_wait_list++] =
-      py::extract<event &>(evt)().data();
-
-    PYOPENCL_CALL_GUARDED_THREADED(clWaitForEvents, (
-          PYOPENCL_WAITLIST_ARGS));
-  }
-
-
-
-
-#if PYOPENCL_CL_VERSION >= 0x1020
-  inline
-  event *enqueue_marker_with_wait_list(command_queue &cq,
-      py::object py_wait_for)
-  {
-    PYOPENCL_PARSE_WAIT_FOR;
-    cl_event evt;
-
-    PYOPENCL_CALL_GUARDED(clEnqueueMarkerWithWaitList, (
-          cq.data(), PYOPENCL_WAITLIST_ARGS, &evt));
-
-    PYOPENCL_RETURN_NEW_EVENT(evt);
-  }
-
-  inline
-  event *enqueue_barrier_with_wait_list(command_queue &cq,
-      py::object py_wait_for)
-  {
-    PYOPENCL_PARSE_WAIT_FOR;
-    cl_event evt;
-
-    PYOPENCL_CALL_GUARDED(clEnqueueBarrierWithWaitList,
-        (cq.data(), PYOPENCL_WAITLIST_ARGS, &evt));
-
-    PYOPENCL_RETURN_NEW_EVENT(evt);
-  }
-#endif
-
-
-  // {{{ used internally for pre-OpenCL-1.2 contexts
-
-  inline
-  event *enqueue_marker(command_queue &cq)
-  {
-    cl_event evt;
-
-    PYOPENCL_CALL_GUARDED(clEnqueueMarker, (
-          cq.data(), &evt));
-
-    PYOPENCL_RETURN_NEW_EVENT(evt);
-  }
-
-  inline
-  void enqueue_wait_for_events(command_queue &cq, py::object py_events)
-  {
-    cl_uint num_events = 0;
-    std::vector<cl_event> event_list(len(py_events));
-
-    PYTHON_FOREACH(py_evt, py_events)
-      event_list[num_events++] =
-      py::extract<event &>(py_evt)().data();
-
-    PYOPENCL_CALL_GUARDED(clEnqueueWaitForEvents, (
-          cq.data(), num_events, event_list.empty( ) ? NULL : &event_list.front()));
-  }
-
-  inline
-  void enqueue_barrier(command_queue &cq)
-  {
-    PYOPENCL_CALL_GUARDED(clEnqueueBarrier, (cq.data()));
-  }
-
-  // }}}
-
-
-#if PYOPENCL_CL_VERSION >= 0x1010
-  class user_event : public event
-  {
-    public:
-      user_event(cl_event evt, bool retain)
-        : event(evt, retain)
-      { }
-
-      void set_status(cl_int execution_status)
-      {
-        PYOPENCL_CALL_GUARDED(clSetUserEventStatus, (data(), execution_status));
-      }
-  };
-
-
-
-
-  inline
-  event *create_user_event(context &ctx)
-  {
-    cl_int status_code;
-    PYOPENCL_PRINT_CALL_TRACE("clCreateUserEvent");
-    cl_event evt = clCreateUserEvent(ctx.data(), &status_code);
-
-    if (status_code != CL_SUCCESS)
-      throw pyopencl::error("UserEvent", status_code);
-
-    try
-    {
-      return new user_event(evt, false);
-    }
-    catch (...)
-    {
-      clReleaseEvent(evt);
-      throw;
-    }
-  }
-
-#endif
-
-  // }}}
-
-  // {{{ memory_object
-
-  py::object create_mem_object_wrapper(cl_mem mem);
-
-  class memory_object_holder
-  {
-    public:
-      virtual const cl_mem data() const = 0;
-
-      PYOPENCL_EQUALITY_TESTS(memory_object_holder);
-
-      size_t size() const
-      {
-        size_t param_value;
-        PYOPENCL_CALL_GUARDED(clGetMemObjectInfo,
-            (data(), CL_MEM_SIZE, sizeof(param_value), &param_value, 0));
-        return param_value;
-      }
-
-      py::object get_info(cl_mem_info param_name) const;
-  };
-
-
-
-
-  class memory_object : boost::noncopyable, public memory_object_holder
-  {
-    private:
-      bool m_valid;
-      cl_mem m_mem;
-      py::object m_hostbuf;
-
-    public:
-      memory_object(cl_mem mem, bool retain, py::object *hostbuf=0)
-        : m_valid(true), m_mem(mem)
-      {
-        if (retain)
-          PYOPENCL_CALL_GUARDED(clRetainMemObject, (mem));
-
-        if (hostbuf)
-          m_hostbuf = *hostbuf;
-      }
-
-      memory_object(memory_object const &src)
-        : m_valid(true), m_mem(src.m_mem), m_hostbuf(src.m_hostbuf)
-      {
-        PYOPENCL_CALL_GUARDED(clRetainMemObject, (m_mem));
-      }
-
-      memory_object(memory_object_holder const &src)
-        : m_valid(true), m_mem(src.data())
-      {
-        PYOPENCL_CALL_GUARDED(clRetainMemObject, (m_mem));
-      }
-
-      void release()
-      {
-        if (!m_valid)
-            throw error("MemoryObject.free", CL_INVALID_VALUE,
-                "trying to double-unref mem object");
-        PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseMemObject, (m_mem));
-        m_valid = false;
-      }
-
-      virtual ~memory_object()
-      {
-        if (m_valid)
-          release();
-      }
-
-      py::object hostbuf()
-      { return m_hostbuf; }
-
-      const cl_mem data() const
-      { return m_mem; }
-
-  };
-
-#if PYOPENCL_CL_VERSION >= 0x1020
-  inline
-  event *enqueue_migrate_mem_objects(
-      command_queue &cq,
-      py::object py_mem_objects,
-      cl_mem_migration_flags flags,
-      py::object py_wait_for)
-  {
-    PYOPENCL_PARSE_WAIT_FOR;
-
-    std::vector<cl_mem> mem_objects;
-    PYTHON_FOREACH(mo, py_mem_objects)
-      mem_objects.push_back(py::extract<memory_object &>(mo)().data());
-
-    cl_event evt;
-    PYOPENCL_RETRY_IF_MEM_ERROR(
-      PYOPENCL_CALL_GUARDED(clEnqueueMigrateMemObjects, (
-            cq.data(),
-            mem_objects.size(), mem_objects.empty( ) ? NULL : &mem_objects.front(),
-            flags,
-            PYOPENCL_WAITLIST_ARGS, &evt
-            ));
-      );
-    PYOPENCL_RETURN_NEW_EVENT(evt);
-  }
-#endif
-
-#ifdef cl_ext_migrate_memobject
-  inline
-  event *enqueue_migrate_mem_object_ext(
-      command_queue &cq,
-      py::object py_mem_objects,
-      cl_mem_migration_flags_ext flags,
-      py::object py_wait_for)
-  {
-    PYOPENCL_PARSE_WAIT_FOR;
-
-#if PYOPENCL_CL_VERSION >= 0x1020
-    // {{{ get platform
-    cl_device_id dev;
-    PYOPENCL_CALL_GUARDED(clGetCommandQueueInfo, (cq.data(), CL_QUEUE_DEVICE,
-          sizeof(dev), &dev, NULL));
-    cl_platform_id plat;
-    PYOPENCL_CALL_GUARDED(clGetDeviceInfo, (cq.data(), CL_DEVICE_PLATFORM,
-          sizeof(plat), &plat, NULL));
-    // }}}
-#endif
-
-    PYOPENCL_GET_EXT_FUN(plat,
-        clEnqueueMigrateMemObjectEXT, enqueue_migrate_fn);
-
-    std::vector<cl_mem> mem_objects;
-    PYTHON_FOREACH(mo, py_mem_objects)
-      mem_objects.push_back(py::extract<memory_object &>(mo)().data());
-
-    cl_event evt;
-    PYOPENCL_RETRY_IF_MEM_ERROR(
-      PYOPENCL_CALL_GUARDED(enqueue_migrate_fn, (
-            cq.data(),
-            mem_objects.size(), mem_objects.empty( ) ? NULL : &mem_objects.front(),
-            flags,
-            PYOPENCL_WAITLIST_ARGS, &evt
-            ));
-      );
-    PYOPENCL_RETURN_NEW_EVENT(evt);
-  }
-#endif
-
-  // }}}
-
-  // {{{ buffer
-
-  inline cl_mem create_buffer(
-      cl_context ctx,
-      cl_mem_flags flags,
-      size_t size,
-      void *host_ptr)
-  {
-    cl_int status_code;
-    PYOPENCL_PRINT_CALL_TRACE("clCreateBuffer");
-    cl_mem mem = clCreateBuffer(ctx, flags, size, host_ptr, &status_code);
-
-    if (status_code != CL_SUCCESS)
-      throw pyopencl::error("create_buffer", status_code);
-
-    return mem;
-  }
-
-
-
-
-  inline cl_mem create_buffer_gc(
-      cl_context ctx,
-      cl_mem_flags flags,
-      size_t size,
-      void *host_ptr)
-  {
-    PYOPENCL_RETRY_RETURN_IF_MEM_ERROR(
-      return create_buffer(ctx, flags, size, host_ptr);
-    );
-  }
-
-
-
-#if PYOPENCL_CL_VERSION >= 0x1010
-  inline cl_mem create_sub_buffer(
-      cl_mem buffer, cl_mem_flags flags, cl_buffer_create_type bct,
-      const void *buffer_create_info)
-  {
-    cl_int status_code;
-    PYOPENCL_PRINT_CALL_TRACE("clCreateSubBuffer");
-    cl_mem mem = clCreateSubBuffer(buffer, flags,
-        bct, buffer_create_info, &status_code);
-
-    if (status_code != CL_SUCCESS)
-      throw pyopencl::error("clCreateSubBuffer", status_code);
-
-    return mem;
-  }
-
-
-
-
-  inline cl_mem create_sub_buffer_gc(
-      cl_mem buffer, cl_mem_flags flags, cl_buffer_create_type bct,
-      const void *buffer_create_info)
-  {
-    PYOPENCL_RETRY_RETURN_IF_MEM_ERROR(
-      return create_sub_buffer(buffer, flags, bct, buffer_create_info);
-    );
-  }
-#endif
-
-
-
-  class buffer : public memory_object
-  {
-    public:
-      buffer(cl_mem mem, bool retain, py::object *hostbuf=0)
-        : memory_object(mem, retain, hostbuf)
-      { }
-
-#if PYOPENCL_CL_VERSION >= 0x1010
-      buffer *get_sub_region(
-          size_t origin, size_t size, cl_mem_flags flags) const
-      {
-        cl_buffer_region region = { origin, size};
-
-        cl_mem mem = create_sub_buffer_gc(
-            data(), flags, CL_BUFFER_CREATE_TYPE_REGION, &region);
-
-        try
-        {
-          return new buffer(mem, false);
-        }
-        catch (...)
-        {
-          PYOPENCL_CALL_GUARDED(clReleaseMemObject, (mem));
-          throw;
-        }
-      }
-
-      buffer *getitem(py::slice slc) const
-      {
-        PYOPENCL_BUFFER_SIZE_T start, end, stride, length;
-
-        size_t my_length;
-        PYOPENCL_CALL_GUARDED(clGetMemObjectInfo,
-            (data(), CL_MEM_SIZE, sizeof(my_length), &my_length, 0));
-
-#if PY_VERSION_HEX >= 0x03020000
-        if (PySlice_GetIndicesEx(slc.ptr(),
-#else
-        if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject *>(slc.ptr()),
-#endif
-              my_length, &start, &end, &stride, &length) != 0)
-          throw py::error_already_set();
-
-        if (stride != 1)
-          throw pyopencl::error("Buffer.__getitem__", CL_INVALID_VALUE,
-              "Buffer slice must have stride 1");
-
-        cl_mem_flags my_flags;
-        PYOPENCL_CALL_GUARDED(clGetMemObjectInfo,
-            (data(), CL_MEM_FLAGS, sizeof(my_flags), &my_flags, 0));
-
-        my_flags &= ~CL_MEM_COPY_HOST_PTR;
-
-        if (end <= start)
-          throw pyopencl::error("Buffer.__getitem__", CL_INVALID_VALUE,
-              "Buffer slice have end > start");
-
-        return get_sub_region(start, end-start, my_flags);
-      }
-#endif
-  };
-
-  // {{{ buffer creation
-
-  inline
-  buffer *create_buffer_py(
-      context &ctx,
-      cl_mem_flags flags,
-      size_t size,
-      py::object py_hostbuf
-      )
-  {
-    if (py_hostbuf.ptr() != Py_None &&
-        !(flags & (CL_MEM_USE_HOST_PTR | CL_MEM_COPY_HOST_PTR)))
-      PyErr_Warn(PyExc_UserWarning, "'hostbuf' was passed, "
-          "but no memory flags to make use of it.");
-
-    void *buf = 0;
-    py::object *retained_buf_obj = 0;
-    if (py_hostbuf.ptr() != Py_None)
-    {
-      PYOPENCL_BUFFER_SIZE_T len;
-      if ((flags & CL_MEM_USE_HOST_PTR)
-          && ((flags & CL_MEM_READ_WRITE)
-            || (flags & CL_MEM_WRITE_ONLY)))
-      {
-        if (PyObject_AsWriteBuffer(py_hostbuf.ptr(), &buf, &len))
-          throw py::error_already_set();
-      }
-      else
-      {
-        if (PyObject_AsReadBuffer(
-              py_hostbuf.ptr(), const_cast<const void **>(&buf), &len))
-          throw py::error_already_set();
-      }
-
-      if (flags & CL_MEM_USE_HOST_PTR)
-        retained_buf_obj = &py_hostbuf;
-
-      if (size > size_t(len))
-        throw pyopencl::error("Buffer", CL_INVALID_VALUE,
-            "specified size is greater than host buffer size");
-      if (size == 0)
-        size = len;
-    }
-
-    cl_mem mem = create_buffer_gc(ctx.data(), flags, size, buf);
-
-    try
-    {
-      return new buffer(mem, false, retained_buf_obj);
-    }
-    catch (...)
-    {
-      PYOPENCL_CALL_GUARDED(clReleaseMemObject, (mem));
-      throw;
-    }
-  }
-
-  // }}}
-
-  // {{{ buffer transfers
-
-  // {{{ byte-for-byte transfers
-
-  inline
-  event *enqueue_read_buffer(
-      command_queue &cq,
-      memory_object_holder &mem,
-      py::object buffer,
-      size_t device_offset,
-      py::object py_wait_for,
-      bool is_blocking)
-  {
-    PYOPENCL_PARSE_WAIT_FOR;
-
-    void *buf;
-    PYOPENCL_BUFFER_SIZE_T len;
-
-    if (PyObject_AsWriteBuffer(buffer.ptr(), &buf, &len))
-      throw py::error_already_set();
-
-    cl_event evt;
-    PYOPENCL_RETRY_IF_MEM_ERROR(
-      PYOPENCL_CALL_GUARDED_THREADED(clEnqueueReadBuffer, (
-            cq.data(),
-            mem.data(),
-            PYOPENCL_CAST_BOOL(is_blocking),
-            device_offset, len, buf,
-            PYOPENCL_WAITLIST_ARGS, &evt
-            ))
-      );
-    PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, buffer);
-  }
-
-
-
-
-  inline
-  event *enqueue_write_buffer(
-      command_queue &cq,
-      memory_object_holder &mem,
-      py::object buffer,
-      size_t device_offset,
-      py::object py_wait_for,
-      bool is_blocking)
-  {
-    PYOPENCL_PARSE_WAIT_FOR;
-
-    const void *buf;
-    PYOPENCL_BUFFER_SIZE_T len;
-
-    if (PyObject_AsReadBuffer(buffer.ptr(), &buf, &len))
-      throw py::error_already_set();
-
-    cl_event evt;
-    PYOPENCL_RETRY_IF_MEM_ERROR(
-      PYOPENCL_CALL_GUARDED_THREADED(clEnqueueWriteBuffer, (
-            cq.data(),
-            mem.data(),
-            PYOPENCL_CAST_BOOL(is_blocking),
-            device_offset, len, buf,
-            PYOPENCL_WAITLIST_ARGS, &evt
-            ))
-      );
-    PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, buffer);
-  }
-
-
-
-
-  inline
-  event *enqueue_copy_buffer(
-      command_queue &cq,
-      memory_object_holder &src,
-      memory_object_holder &dst,
-      ptrdiff_t byte_count,
-      size_t src_offset,
-      size_t dst_offset,
-      py::object py_wait_for)
-  {
-    PYOPENCL_PARSE_WAIT_FOR;
-
-    if (byte_count < 0)
-    {
-      size_t byte_count_src = 0;
-      size_t byte_count_dst = 0;
-      PYOPENCL_CALL_GUARDED(clGetMemObjectInfo,
-          (src.data(), CL_MEM_SIZE, sizeof(byte_count), &byte_count_src, 0));
-      PYOPENCL_CALL_GUARDED(clGetMemObjectInfo,
-          (src.data(), CL_MEM_SIZE, sizeof(byte_count), &byte_count_dst, 0));
-      byte_count = std::min(byte_count_src, byte_count_dst);
-    }
-
-    cl_event evt;
-    PYOPENCL_RETRY_IF_MEM_ERROR(
-      PYOPENCL_CALL_GUARDED(clEnqueueCopyBuffer, (
-            cq.data(),
-            src.data(), dst.data(),
-            src_offset, dst_offset,
-            byte_count,
-            PYOPENCL_WAITLIST_ARGS,
-            &evt
-            ))
-      );
-
-    PYOPENCL_RETURN_NEW_EVENT(evt);
-  }
-
-  // }}}
-
-  // {{{ rectangular transfers
-#if PYOPENCL_CL_VERSION >= 0x1010
-  inline
-  event *enqueue_read_buffer_rect(
-      command_queue &cq,
-      memory_object_holder &mem,
-      py::object buffer,
-      py::object py_buffer_origin,
-      py::object py_host_origin,
-      py::object py_region,
-      py::object py_buffer_pitches,
-      py::object py_host_pitches,
-      py::object py_wait_for,
-      bool is_blocking
-      )
-  {
-    PYOPENCL_PARSE_WAIT_FOR;
-    COPY_PY_COORD_TRIPLE(buffer_origin);
-    COPY_PY_COORD_TRIPLE(host_origin);
-    COPY_PY_REGION_TRIPLE(region);
-    COPY_PY_PITCH_TUPLE(buffer_pitches);
-    COPY_PY_PITCH_TUPLE(host_pitches);
-
-    void *buf;
-    PYOPENCL_BUFFER_SIZE_T len;
-
-    if (PyObject_AsWriteBuffer(buffer.ptr(), &buf, &len))
-      throw py::error_already_set();
-
-    cl_event evt;
-    PYOPENCL_RETRY_IF_MEM_ERROR(
-      PYOPENCL_CALL_GUARDED_THREADED(clEnqueueReadBufferRect, (
-            cq.data(),
-            mem.data(),
-            PYOPENCL_CAST_BOOL(is_blocking),
-            buffer_origin, host_origin, region,
-            buffer_pitches[0], buffer_pitches[1],
-            host_pitches[0], host_pitches[1],
-            buf,
-            PYOPENCL_WAITLIST_ARGS, &evt
-            ))
-      );
-    PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, buffer);
-  }
-
-
-
-
-  inline
-  event *enqueue_write_buffer_rect(
-      command_queue &cq,
-      memory_object_holder &mem,
-      py::object buffer,
-      py::object py_buffer_origin,
-      py::object py_host_origin,
-      py::object py_region,
-      py::object py_buffer_pitches,
-      py::object py_host_pitches,
-      py::object py_wait_for,
-      bool is_blocking
-      )
-  {
-    PYOPENCL_PARSE_WAIT_FOR;
-    COPY_PY_COORD_TRIPLE(buffer_origin);
-    COPY_PY_COORD_TRIPLE(host_origin);
-    COPY_PY_REGION_TRIPLE(region);
-    COPY_PY_PITCH_TUPLE(buffer_pitches);
-    COPY_PY_PITCH_TUPLE(host_pitches);
-
-    const void *buf;
-    PYOPENCL_BUFFER_SIZE_T len;
-
-    if (PyObject_AsReadBuffer(buffer.ptr(), &buf, &len))
-      throw py::error_already_set();
-
-    cl_event evt;
-    PYOPENCL_RETRY_IF_MEM_ERROR(
-      PYOPENCL_CALL_GUARDED_THREADED(clEnqueueWriteBufferRect, (
-            cq.data(),
-            mem.data(),
-            PYOPENCL_CAST_BOOL(is_blocking),
-            buffer_origin, host_origin, region,
-            buffer_pitches[0], buffer_pitches[1],
-            host_pitches[0], host_pitches[1],
-            buf,
-            PYOPENCL_WAITLIST_ARGS, &evt
-            ))
-      );
-    PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, buffer);
-  }
-
-
-
-
-  inline
-  event *enqueue_copy_buffer_rect(
-      command_queue &cq,
-      memory_object_holder &src,
-      memory_object_holder &dst,
-      py::object py_src_origin,
-      py::object py_dst_origin,
-      py::object py_region,
-      py::object py_src_pitches,
-      py::object py_dst_pitches,
-      py::object py_wait_for)
-  {
-    PYOPENCL_PARSE_WAIT_FOR;
-    COPY_PY_COORD_TRIPLE(src_origin);
-    COPY_PY_COORD_TRIPLE(dst_origin);
-    COPY_PY_REGION_TRIPLE(region);
-    COPY_PY_PITCH_TUPLE(src_pitches);
-    COPY_PY_PITCH_TUPLE(dst_pitches);
-
-    cl_event evt;
-    PYOPENCL_RETRY_IF_MEM_ERROR(
-      PYOPENCL_CALL_GUARDED(clEnqueueCopyBufferRect, (
-            cq.data(),
-            src.data(), dst.data(),
-            src_origin, dst_origin, region,
-            src_pitches[0], src_pitches[1],
-            dst_pitches[0], dst_pitches[1],
-            PYOPENCL_WAITLIST_ARGS,
-            &evt
-            ))
-      );
-
-    PYOPENCL_RETURN_NEW_EVENT(evt);
-  }
-
-#endif
-
-  // }}}
-
-  // }}}
-
-#if PYOPENCL_CL_VERSION >= 0x1020
-  inline
-  event *enqueue_fill_buffer(
-      command_queue &cq,
-      memory_object_holder &mem,
-      py::object pattern,
-      size_t offset,
-      size_t size,
-      py::object py_wait_for
-      )
-  {
-    PYOPENCL_PARSE_WAIT_FOR;
-
-    const void *pattern_buf;
-    PYOPENCL_BUFFER_SIZE_T pattern_len;
-
-    if (PyObject_AsReadBuffer(pattern.ptr(), &pattern_buf, &pattern_len))
-      throw py::error_already_set();
-
-    cl_event evt;
-    PYOPENCL_RETRY_IF_MEM_ERROR(
-      PYOPENCL_CALL_GUARDED(clEnqueueFillBuffer, (
-            cq.data(),
-            mem.data(),
-            pattern_buf, pattern_len, offset, size,
-            PYOPENCL_WAITLIST_ARGS, &evt
-            ))
-      );
-    PYOPENCL_RETURN_NEW_EVENT(evt);
-  }
-#endif
-
-  // }}}
-
-  // {{{ image
-
-  class image : public memory_object
-  {
-    public:
-      image(cl_mem mem, bool retain, py::object *hostbuf=0)
-        : memory_object(mem, retain, hostbuf)
-      { }
-
-      py::object get_image_info(cl_image_info param_name) const
-      {
-        switch (param_name)
-        {
-          case CL_IMAGE_FORMAT:
-            PYOPENCL_GET_INTEGRAL_INFO(Image, data(), param_name,
-                cl_image_format);
-          case CL_IMAGE_ELEMENT_SIZE:
-          case CL_IMAGE_ROW_PITCH:
-          case CL_IMAGE_SLICE_PITCH:
-          case CL_IMAGE_WIDTH:
-          case CL_IMAGE_HEIGHT:
-          case CL_IMAGE_DEPTH:
-#if PYOPENCL_CL_VERSION >= 0x1020
-          case CL_IMAGE_ARRAY_SIZE:
-#endif
-            PYOPENCL_GET_INTEGRAL_INFO(Image, data(), param_name, size_t);
-
-#if PYOPENCL_CL_VERSION >= 0x1020
-          case CL_IMAGE_BUFFER:
-            {
-              cl_mem param_value;
-              PYOPENCL_CALL_GUARDED(clGetImageInfo, \
-                  (data(), param_name, sizeof(param_value), &param_value, 0));
-              if (param_value == 0)
-              {
-                // no associated memory object? no problem.
-                return py::object();
-              }
-
-              return create_mem_object_wrapper(param_value);
-            }
-
-          case CL_IMAGE_NUM_MIP_LEVELS:
-          case CL_IMAGE_NUM_SAMPLES:
-            PYOPENCL_GET_INTEGRAL_INFO(Image, data(), param_name, cl_uint);
-#endif
-
-          default:
-            throw error("MemoryObject.get_image_info", CL_INVALID_VALUE);
-        }
-      }
-  };
-
-
-
-
-  // {{{ image formats
-
-  inline
-  cl_image_format *make_image_format(cl_channel_order ord, cl_channel_type tp)
-  {
-    std::auto_ptr<cl_image_format> result(new cl_image_format);
-    result->image_channel_order = ord;
-    result->image_channel_data_type = tp;
-    return result.release();
-  }
-
-  inline
-  py::list get_supported_image_formats(
-      context const &ctx,
-      cl_mem_flags flags,
-      cl_mem_object_type image_type)
-  {
-    cl_uint num_image_formats;
-    PYOPENCL_CALL_GUARDED(clGetSupportedImageFormats, (
-          ctx.data(), flags, image_type,
-          0, NULL, &num_image_formats));
-
-    std::vector<cl_image_format> formats(num_image_formats);
-    PYOPENCL_CALL_GUARDED(clGetSupportedImageFormats, (
-          ctx.data(), flags, image_type,
-          formats.size(), formats.empty( ) ? NULL : &formats.front(), NULL));
-
-    PYOPENCL_RETURN_VECTOR(cl_image_format, formats);
-  }
-
-  inline
-  cl_uint get_image_format_channel_count(cl_image_format const &fmt)
-  {
-    switch (fmt.image_channel_order)
-    {
-      case CL_R: return 1;
-      case CL_A: return 1;
-      case CL_RG: return 2;
-      case CL_RA: return 2;
-      case CL_RGB: return 3;
-      case CL_RGBA: return 4;
-      case CL_BGRA: return 4;
-      case CL_INTENSITY: return 1;
-      case CL_LUMINANCE: return 1;
-      default:
-        throw pyopencl::error("ImageFormat.channel_dtype_size",
-            CL_INVALID_VALUE,
-            "unrecognized channel order");
-    }
-  }
-
-  inline
-  cl_uint get_image_format_channel_dtype_size(cl_image_format const &fmt)
-  {
-    switch (fmt.image_channel_data_type)
-    {
-      case CL_SNORM_INT8: return 1;
-      case CL_SNORM_INT16: return 2;
-      case CL_UNORM_INT8: return 1;
-      case CL_UNORM_INT16: return 2;
-      case CL_UNORM_SHORT_565: return 2;
-      case CL_UNORM_SHORT_555: return 2;
-      case CL_UNORM_INT_101010: return 4;
-      case CL_SIGNED_INT8: return 1;
-      case CL_SIGNED_INT16: return 2;
-      case CL_SIGNED_INT32: return 4;
-      case CL_UNSIGNED_INT8: return 1;
-      case CL_UNSIGNED_INT16: return 2;
-      case CL_UNSIGNED_INT32: return 4;
-      case CL_HALF_FLOAT: return 2;
-      case CL_FLOAT: return 4;
-      default:
-        throw pyopencl::error("ImageFormat.channel_dtype_size",
-            CL_INVALID_VALUE,
-            "unrecognized channel data type");
-    }
-  }
-
-  inline
-  cl_uint get_image_format_item_size(cl_image_format const &fmt)
-  {
-    return get_image_format_channel_count(fmt)
-      * get_image_format_channel_dtype_size(fmt);
-  }
-
-  // }}}
-
-  // {{{ image creation
-
-  inline
-  image *create_image(
-      context const &ctx,
-      cl_mem_flags flags,
-      cl_image_format const &fmt,
-      py::object shape,
-      py::object pitches,
-      py::object buffer)
-  {
-    if (shape.ptr() == Py_None)
-      throw pyopencl::error("Image", CL_INVALID_VALUE,
-          "'shape' must be given");
-
-    void *buf = 0;
-    PYOPENCL_BUFFER_SIZE_T len;
-    py::object *retained_buf_obj = 0;
-
-    if (buffer.ptr() != Py_None)
-    {
-      if ((flags & CL_MEM_USE_HOST_PTR)
-          && ((flags & CL_MEM_READ_WRITE)
-            || (flags & CL_MEM_WRITE_ONLY)))
-      {
-        if (PyObject_AsWriteBuffer(buffer.ptr(), &buf, &len))
-          throw py::error_already_set();
-      }
-      else
-      {
-        if (PyObject_AsReadBuffer(
-              buffer.ptr(), const_cast<const void **>(&buf), &len))
-          throw py::error_already_set();
-      }
-
-      if (flags & CL_MEM_USE_HOST_PTR)
-        retained_buf_obj = &buffer;
-    }
-
-    unsigned dims = py::len(shape);
-    cl_int status_code;
-    cl_mem mem;
-    if (dims == 2)
-    {
-      size_t width = py::extract<size_t>(shape[0]);
-      size_t height = py::extract<size_t>(shape[1]);
-
-      size_t pitch = 0;
-      if (pitches.ptr() != Py_None)
-      {
-        if (py::len(pitches) != 1)
-          throw pyopencl::error("Image", CL_INVALID_VALUE,
-              "invalid length of pitch tuple");
-        pitch = py::extract<size_t>(pitches[0]);
-      }
-
-      // check buffer size
-      cl_int itemsize = get_image_format_item_size(fmt);
-      if (buf && std::max(pitch, width*itemsize)*height > cl_uint(len))
-          throw pyopencl::error("Image", CL_INVALID_VALUE,
-              "buffer too small");
-
-      PYOPENCL_PRINT_CALL_TRACE("clCreateImage2D");
-      PYOPENCL_RETRY_IF_MEM_ERROR(
-          {
-            mem = clCreateImage2D(ctx.data(), flags, &fmt,
-                width, height, pitch, buf, &status_code);
-            if (status_code != CL_SUCCESS)
-              throw pyopencl::error("clCreateImage2D", status_code);
-          } );
-
-    }
-    else if (dims == 3)
-    {
-      size_t width = py::extract<size_t>(shape[0]);
-      size_t height = py::extract<size_t>(shape[1]);
-      size_t depth = py::extract<size_t>(shape[2]);
-
-      size_t pitch_x = 0;
-      size_t pitch_y = 0;
-
-      if (pitches.ptr() != Py_None)
-      {
-        if (py::len(pitches) != 2)
-          throw pyopencl::error("Image", CL_INVALID_VALUE,
-              "invalid length of pitch tuple");
-
-        pitch_x = py::extract<size_t>(pitches[0]);
-        pitch_y = py::extract<size_t>(pitches[1]);
-      }
-
-      // check buffer size
-      cl_int itemsize = get_image_format_item_size(fmt);
-      if (buf &&
-          std::max(std::max(pitch_x, width*itemsize)*height, pitch_y)
-          * depth > cl_uint(len))
-        throw pyopencl::error("Image", CL_INVALID_VALUE,
-            "buffer too small");
-
-      PYOPENCL_PRINT_CALL_TRACE("clCreateImage3D");
-      PYOPENCL_RETRY_IF_MEM_ERROR(
-          {
-            mem = clCreateImage3D(ctx.data(), flags, &fmt,
-              width, height, depth, pitch_x, pitch_y, buf, &status_code);
-            if (status_code != CL_SUCCESS)
-              throw pyopencl::error("clCreateImage3D", status_code);
-          } );
-    }
-    else
-      throw pyopencl::error("Image", CL_INVALID_VALUE,
-          "invalid dimension");
-
-    try
-    {
-      return new image(mem, false, retained_buf_obj);
-    }
-    catch (...)
-    {
-      PYOPENCL_CALL_GUARDED(clReleaseMemObject, (mem));
-      throw;
-    }
-  }
-
-#if PYOPENCL_CL_VERSION >= 0x1020
-
-  inline
-  image *create_image_from_desc(
-      context const &ctx,
-      cl_mem_flags flags,
-      cl_image_format const &fmt,
-      cl_image_desc &desc,
-      py::object buffer)
-  {
-    if (buffer.ptr() != Py_None &&
-        !(flags & (CL_MEM_USE_HOST_PTR | CL_MEM_COPY_HOST_PTR)))
-      PyErr_Warn(PyExc_UserWarning, "'hostbuf' was passed, "
-          "but no memory flags to make use of it.");
-
-    void *buf = 0;
-    PYOPENCL_BUFFER_SIZE_T len;
-    py::object *retained_buf_obj = 0;
-
-    if (buffer.ptr() != Py_None)
-    {
-      if (flags & CL_MEM_USE_HOST_PTR)
-      {
-        if (PyObject_AsWriteBuffer(buffer.ptr(), &buf, &len))
-          throw py::error_already_set();
-      }
-      else
-      {
-        if (PyObject_AsReadBuffer(
-              buffer.ptr(), const_cast<const void **>(&buf), &len))
-          throw py::error_already_set();
-      }
-
-      if (flags & CL_MEM_USE_HOST_PTR)
-        retained_buf_obj = &buffer;
-    }
-
-    PYOPENCL_PRINT_CALL_TRACE("clCreateImage");
-    cl_int status_code;
-    cl_mem mem = clCreateImage(ctx.data(), flags, &fmt, &desc, buf, &status_code);
-    if (status_code != CL_SUCCESS)
-      throw pyopencl::error("clCreateImage", status_code);
-
-    try
-    {
-      return new image(mem, false, retained_buf_obj);
-    }
-    catch (...)
-    {
-      PYOPENCL_CALL_GUARDED(clReleaseMemObject, (mem));
-      throw;
-    }
-  }
-
-#endif
-
-  // }}}
-
-  // {{{ image transfers
-
-  inline
-  event *enqueue_read_image(
-      command_queue &cq,
-      image &img,
-      py::object py_origin, py::object py_region,
-      py::object buffer,
-      size_t row_pitch, size_t slice_pitch,
-      py::object py_wait_for,
-      bool is_blocking)
-  {
-    PYOPENCL_PARSE_WAIT_FOR;
-    COPY_PY_COORD_TRIPLE(origin);
-    COPY_PY_REGION_TRIPLE(region);
-
-    void *buf;
-    PYOPENCL_BUFFER_SIZE_T len;
-
-    if (PyObject_AsWriteBuffer(buffer.ptr(), &buf, &len))
-      throw py::error_already_set();
-
-    cl_event evt;
-
-    PYOPENCL_RETRY_IF_MEM_ERROR(
-      PYOPENCL_CALL_GUARDED(clEnqueueReadImage, (
-            cq.data(),
-            img.data(),
-            PYOPENCL_CAST_BOOL(is_blocking),
-            origin, region, row_pitch, slice_pitch, buf,
-            PYOPENCL_WAITLIST_ARGS, &evt
-            ));
-      );
-    PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, buffer);
-  }
-
-
-
-
-  inline
-  event *enqueue_write_image(
-      command_queue &cq,
-      image &img,
-      py::object py_origin, py::object py_region,
-      py::object buffer,
-      size_t row_pitch, size_t slice_pitch,
-      py::object py_wait_for,
-      bool is_blocking)
-  {
-    PYOPENCL_PARSE_WAIT_FOR;
-    COPY_PY_COORD_TRIPLE(origin);
-    COPY_PY_REGION_TRIPLE(region);
-
-    const void *buf;
-    PYOPENCL_BUFFER_SIZE_T len;
-
-    if (PyObject_AsReadBuffer(buffer.ptr(), &buf, &len))
-      throw py::error_already_set();
-
-    cl_event evt;
-    PYOPENCL_RETRY_IF_MEM_ERROR(
-      PYOPENCL_CALL_GUARDED(clEnqueueWriteImage, (
-            cq.data(),
-            img.data(),
-            PYOPENCL_CAST_BOOL(is_blocking),
-            origin, region, row_pitch, slice_pitch, buf,
-            PYOPENCL_WAITLIST_ARGS, &evt
-            ));
-      );
-    PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, buffer);
-  }
-
-
-
-
-  inline
-  event *enqueue_copy_image(
-      command_queue &cq,
-      memory_object_holder &src,
-      memory_object_holder &dest,
-      py::object py_src_origin,
-      py::object py_dest_origin,
-      py::object py_region,
-      py::object py_wait_for
-      )
-  {
-    PYOPENCL_PARSE_WAIT_FOR;
-    COPY_PY_COORD_TRIPLE(src_origin);
-    COPY_PY_COORD_TRIPLE(dest_origin);
-    COPY_PY_REGION_TRIPLE(region);
-
-    cl_event evt;
-    PYOPENCL_RETRY_IF_MEM_ERROR(
-      PYOPENCL_CALL_GUARDED(clEnqueueCopyImage, (
-            cq.data(), src.data(), dest.data(),
-            src_origin, dest_origin, region,
-            PYOPENCL_WAITLIST_ARGS, &evt
-            ));
-      );
-    PYOPENCL_RETURN_NEW_EVENT(evt);
-  }
-
-
-
-
-  inline
-  event *enqueue_copy_image_to_buffer(
-      command_queue &cq,
-      memory_object_holder &src,
-      memory_object_holder &dest,
-      py::object py_origin,
-      py::object py_region,
-      size_t offset,
-      py::object py_wait_for
-      )
-  {
-    PYOPENCL_PARSE_WAIT_FOR;
-    COPY_PY_COORD_TRIPLE(origin);
-    COPY_PY_REGION_TRIPLE(region);
-
-    cl_event evt;
-    PYOPENCL_RETRY_IF_MEM_ERROR(
-      PYOPENCL_CALL_GUARDED(clEnqueueCopyImageToBuffer, (
-            cq.data(), src.data(), dest.data(),
-            origin, region, offset,
-            PYOPENCL_WAITLIST_ARGS, &evt
-            ));
-      );
-    PYOPENCL_RETURN_NEW_EVENT(evt);
-  }
-
-
-
-
-  inline
-  event *enqueue_copy_buffer_to_image(
-      command_queue &cq,
-      memory_object_holder &src,
-      memory_object_holder &dest,
-      size_t offset,
-      py::object py_origin,
-      py::object py_region,
-      py::object py_wait_for
-      )
-  {
-    PYOPENCL_PARSE_WAIT_FOR;
-    COPY_PY_COORD_TRIPLE(origin);
-    COPY_PY_REGION_TRIPLE(region);
-
-    cl_event evt;
-    PYOPENCL_RETRY_IF_MEM_ERROR(
-      PYOPENCL_CALL_GUARDED(clEnqueueCopyBufferToImage, (
-            cq.data(), src.data(), dest.data(),
-            offset, origin, region,
-            PYOPENCL_WAITLIST_ARGS, &evt
-            ));
-      );
-    PYOPENCL_RETURN_NEW_EVENT(evt);
-  }
-
-  // }}}
-
-#if PYOPENCL_CL_VERSION >= 0x1020
-  inline
-  event *enqueue_fill_image(
-      command_queue &cq,
-      memory_object_holder &mem,
-      py::object color,
-      py::object py_origin, py::object py_region,
-      py::object py_wait_for
-      )
-  {
-    PYOPENCL_PARSE_WAIT_FOR;
-
-    COPY_PY_COORD_TRIPLE(origin);
-    COPY_PY_REGION_TRIPLE(region);
-
-    const void *color_buf;
-    PYOPENCL_BUFFER_SIZE_T color_len;
-
-    if (PyObject_AsReadBuffer(color.ptr(), &color_buf, &color_len))
-      throw py::error_already_set();
-
-    cl_event evt;
-    PYOPENCL_RETRY_IF_MEM_ERROR(
-      PYOPENCL_CALL_GUARDED(clEnqueueFillImage, (
-            cq.data(),
-            mem.data(),
-            color_buf, origin, region,
-            PYOPENCL_WAITLIST_ARGS, &evt
-            ));
-      );
-    PYOPENCL_RETURN_NEW_EVENT(evt);
-  }
-#endif
-
-  // }}}
-
-  // {{{ maps
-  class memory_map
-  {
-    private:
-      bool m_valid;
-      command_queue m_queue;
-      memory_object m_mem;
-      void *m_ptr;
-
-    public:
-      memory_map(command_queue &cq, memory_object const &mem, void *ptr)
-        : m_valid(true), m_queue(cq), m_mem(mem), m_ptr(ptr)
-      {
-      }
-
-      ~memory_map()
-      {
-        if (m_valid)
-          delete release(0, py::object());
-      }
-
-      event *release(command_queue *cq, py::object py_wait_for)
-      {
-        PYOPENCL_PARSE_WAIT_FOR;
-
-        if (cq == 0)
-          cq = &m_queue;
-
-        cl_event evt;
-        PYOPENCL_CALL_GUARDED(clEnqueueUnmapMemObject, (
-              cq->data(), m_mem.data(), m_ptr,
-              PYOPENCL_WAITLIST_ARGS, &evt
-              ));
-
-        m_valid = false;
-
-        PYOPENCL_RETURN_NEW_EVENT(evt);
-      }
-  };
-
-
-
-
-  inline
-  py::object enqueue_map_buffer(
-      command_queue &cq,
-      memory_object_holder &buf,
-      cl_map_flags flags,
-      size_t offset,
-      py::object py_shape, py::object dtype,
-      py::object py_order, py::object py_strides,
-      py::object py_wait_for,
-      bool is_blocking
-      )
-  {
-    PYOPENCL_PARSE_WAIT_FOR;
-    PYOPENCL_PARSE_NUMPY_ARRAY_SPEC;
-
-    npy_uintp size_in_bytes = tp_descr->elsize;
-    BOOST_FOREACH(npy_intp sdim, shape)
-      size_in_bytes *= sdim;
-
-    py::handle<> result;
-
-    cl_event evt;
-    cl_int status_code;
-    PYOPENCL_PRINT_CALL_TRACE("clEnqueueMapBuffer");
-    void *mapped;
-
-    PYOPENCL_RETRY_IF_MEM_ERROR(
-        {
-          Py_BEGIN_ALLOW_THREADS
-          mapped = clEnqueueMapBuffer(
-                cq.data(), buf.data(),
-                PYOPENCL_CAST_BOOL(is_blocking), flags,
-                offset, size_in_bytes,
-                PYOPENCL_WAITLIST_ARGS, &evt,
-                &status_code);
-          Py_END_ALLOW_THREADS
-          if (status_code != CL_SUCCESS)
-            throw pyopencl::error("clEnqueueMapBuffer", status_code);
-        } );
-
-    event evt_handle(evt, false);
-
-    std::auto_ptr<memory_map> map;
-    try
-    {
-      result = py::handle<>(PyArray_NewFromDescr(
-          &PyArray_Type, tp_descr,
-          shape.size(),
-          shape.empty() ? NULL : &shape.front(),
-          strides.empty() ? NULL : &strides.front(),
-          mapped, ary_flags, /*obj*/NULL));
-
-      if (size_in_bytes != (npy_uintp) PyArray_NBYTES(result.get()))
-        throw pyopencl::error("enqueue_map_buffer", CL_INVALID_VALUE,
-            "miscalculated numpy array size (not contiguous?)");
-
-       map = std::auto_ptr<memory_map>(new memory_map(cq, buf, mapped));
-    }
-    catch (...)
-    {
-      PYOPENCL_CALL_GUARDED_CLEANUP(clEnqueueUnmapMemObject, (
-            cq.data(), buf.data(), mapped, 0, 0, 0));
-      throw;
-    }
-
-    py::handle<> map_py(handle_from_new_ptr(map.release()));
-    PyArray_BASE(result.get()) = map_py.get();
-    Py_INCREF(map_py.get());
-
-    return py::make_tuple(
-        result,
-        handle_from_new_ptr(new event(evt_handle)));
-  }
-
-
-
-
-  inline
-  py::object enqueue_map_image(
-      command_queue &cq,
-      memory_object_holder &img,
-      cl_map_flags flags,
-      py::object py_origin,
-      py::object py_region,
-      py::object py_shape, py::object dtype,
-      py::object py_order, py::object py_strides,
-      py::object py_wait_for,
-      bool is_blocking
-      )
-  {
-    PYOPENCL_PARSE_WAIT_FOR;
-    PYOPENCL_PARSE_NUMPY_ARRAY_SPEC;
-    COPY_PY_COORD_TRIPLE(origin);
-    COPY_PY_REGION_TRIPLE(region);
-
-    cl_event evt;
-    cl_int status_code;
-    PYOPENCL_PRINT_CALL_TRACE("clEnqueueMapImage");
-    size_t row_pitch, slice_pitch;
-    void *mapped;
-    PYOPENCL_RETRY_IF_MEM_ERROR(
-      {
-        Py_BEGIN_ALLOW_THREADS
-        mapped = clEnqueueMapImage(
-              cq.data(), img.data(),
-              PYOPENCL_CAST_BOOL(is_blocking), flags,
-              origin, region, &row_pitch, &slice_pitch,
-              PYOPENCL_WAITLIST_ARGS, &evt,
-              &status_code);
-        Py_END_ALLOW_THREADS
-        if (status_code != CL_SUCCESS)
-          throw pyopencl::error("clEnqueueMapImage", status_code);
-      } );
-
-    event evt_handle(evt, false);
-
-    std::auto_ptr<memory_map> map;
-    try
-    {
-       map = std::auto_ptr<memory_map>(new memory_map(cq, img, mapped));
-    }
-    catch (...)
-    {
-      PYOPENCL_CALL_GUARDED_CLEANUP(clEnqueueUnmapMemObject, (
-            cq.data(), img.data(), mapped, 0, 0, 0));
-      throw;
-    }
-
-    py::handle<> result = py::handle<>(PyArray_NewFromDescr(
-        &PyArray_Type, tp_descr,
-        shape.size(),
-        shape.empty() ? NULL : &shape.front(),
-        strides.empty() ? NULL : &strides.front(),
-        mapped, ary_flags, /*obj*/NULL));
-
-    py::handle<> map_py(handle_from_new_ptr(map.release()));
-    PyArray_BASE(result.get()) = map_py.get();
-    Py_INCREF(map_py.get());
-
-    return py::make_tuple(
-        result,
-        handle_from_new_ptr(new event(evt_handle)),
-        row_pitch, slice_pitch);
-  }
-
-  // }}}
-
-  // {{{ sampler
-  class sampler : boost::noncopyable
-  {
-    private:
-      cl_sampler m_sampler;
-
-    public:
-      sampler(context const &ctx, bool normalized_coordinates,
-          cl_addressing_mode am, cl_filter_mode fm)
-      {
-        cl_int status_code;
-        PYOPENCL_PRINT_CALL_TRACE("clCreateSampler");
-        m_sampler = clCreateSampler(
-            ctx.data(),
-            normalized_coordinates,
-            am, fm, &status_code);
-
-        if (status_code != CL_SUCCESS)
-          throw pyopencl::error("Sampler", status_code);
-      }
-
-      sampler(cl_sampler samp, bool retain)
-        : m_sampler(samp)
-      {
-        if (retain)
-          PYOPENCL_CALL_GUARDED(clRetainSampler, (samp));
-      }
-
-      ~sampler()
-      {
-        PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseSampler, (m_sampler));
-      }
-
-      cl_sampler data() const
-      {
-        return m_sampler;
-      }
-
-      PYOPENCL_EQUALITY_TESTS(sampler);
-
-      py::object get_info(cl_sampler_info param_name) const
-      {
-        switch (param_name)
-        {
-          case CL_SAMPLER_REFERENCE_COUNT:
-            PYOPENCL_GET_INTEGRAL_INFO(Sampler, m_sampler, param_name,
-                cl_uint);
-          case CL_SAMPLER_CONTEXT:
-            PYOPENCL_GET_OPAQUE_INFO(Sampler, m_sampler, param_name,
-                cl_context, context);
-          case CL_SAMPLER_ADDRESSING_MODE:
-            PYOPENCL_GET_INTEGRAL_INFO(Sampler, m_sampler, param_name,
-                cl_addressing_mode);
-          case CL_SAMPLER_FILTER_MODE:
-            PYOPENCL_GET_INTEGRAL_INFO(Sampler, m_sampler, param_name,
-                cl_filter_mode);
-          case CL_SAMPLER_NORMALIZED_COORDS:
-            PYOPENCL_GET_INTEGRAL_INFO(Sampler, m_sampler, param_name,
-                cl_bool);
-
-          default:
-            throw error("Sampler.get_info", CL_INVALID_VALUE);
-        }
-      }
-  };
-
-  // }}}
-
-  // {{{ program
-
-  class program : boost::noncopyable
-  {
-    public:
-      enum program_kind_type { KND_UNKNOWN, KND_SOURCE, KND_BINARY };
-
-    private:
-      cl_program m_program;
-      program_kind_type m_program_kind;
-
-    public:
-      program(cl_program prog, bool retain, program_kind_type progkind=KND_UNKNOWN)
-        : m_program(prog), m_program_kind(progkind)
-      {
-        if (retain)
-          PYOPENCL_CALL_GUARDED(clRetainProgram, (prog));
-      }
-
-      ~program()
-      {
-        PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseProgram, (m_program));
-      }
-
-      cl_program data() const
-      {
-        return m_program;
-      }
-
-      program_kind_type kind() const
-      {
-        return m_program_kind;
-      }
-
-      PYOPENCL_EQUALITY_TESTS(program);
-
-      py::object get_info(cl_program_info param_name) const
-      {
-        switch (param_name)
-        {
-          case CL_PROGRAM_REFERENCE_COUNT:
-            PYOPENCL_GET_INTEGRAL_INFO(Program, m_program, param_name,
-                cl_uint);
-          case CL_PROGRAM_CONTEXT:
-            PYOPENCL_GET_OPAQUE_INFO(Program, m_program, param_name,
-                cl_context, context);
-          case CL_PROGRAM_NUM_DEVICES:
-            PYOPENCL_GET_INTEGRAL_INFO(Program, m_program, param_name,
-                cl_uint);
-          case CL_PROGRAM_DEVICES:
-            {
-              std::vector<cl_device_id> result;
-              PYOPENCL_GET_VEC_INFO(Program, m_program, param_name, result);
-
-              py::list py_result;
-              BOOST_FOREACH(cl_device_id did, result)
-                py_result.append(handle_from_new_ptr(
-                      new pyopencl::device(did)));
-              return py_result;
-            }
-          case CL_PROGRAM_SOURCE:
-            PYOPENCL_GET_STR_INFO(Program, m_program, param_name);
-          case CL_PROGRAM_BINARY_SIZES:
-            {
-              std::vector<size_t> result;
-              PYOPENCL_GET_VEC_INFO(Program, m_program, param_name, result);
-              PYOPENCL_RETURN_VECTOR(size_t, result);
-            }
-          case CL_PROGRAM_BINARIES:
-            // {{{
-            {
-              std::vector<size_t> sizes;
-              PYOPENCL_GET_VEC_INFO(Program, m_program, CL_PROGRAM_BINARY_SIZES, sizes);
-
-              size_t total_size = std::accumulate(sizes.begin(), sizes.end(), 0);
-
-              boost::scoped_array<unsigned char> result(
-                  new unsigned char[total_size]);
-              std::vector<unsigned char *> result_ptrs;
-
-              unsigned char *ptr = result.get();
-              for (unsigned i = 0; i < sizes.size(); ++i)
-              {
-                result_ptrs.push_back(ptr);
-                ptr += sizes[i];
-              }
-
-              PYOPENCL_CALL_GUARDED(clGetProgramInfo,
-                  (m_program, param_name, sizes.size()*sizeof(unsigned char *),
-                   result_ptrs.empty( ) ? NULL : &result_ptrs.front(), 0)); \
-
-              py::list py_result;
-              ptr = result.get();
-              for (unsigned i = 0; i < sizes.size(); ++i)
-              {
-                py::handle<> binary_pyobj(
-#if PY_VERSION_HEX >= 0x03000000
-                    PyBytes_FromStringAndSize(
-                      reinterpret_cast<char *>(ptr), sizes[i])
-#else
-                    PyString_FromStringAndSize(
-                      reinterpret_cast<char *>(ptr), sizes[i])
-#endif
-                    );
-                py_result.append(binary_pyobj);
-                ptr += sizes[i];
-              }
-              return py_result;
-            }
-            // }}}
-#if PYOPENCL_CL_VERSION >= 0x1020
-          case CL_PROGRAM_NUM_KERNELS:
-            PYOPENCL_GET_INTEGRAL_INFO(Program, m_program, param_name,
-                size_t);
-          case CL_PROGRAM_KERNEL_NAMES:
-            PYOPENCL_GET_STR_INFO(Program, m_program, param_name);
-#endif
-
-          default:
-            throw error("Program.get_info", CL_INVALID_VALUE);
-        }
-      }
-
-      py::object get_build_info(
-          device const &dev,
-          cl_program_build_info param_name) const
-      {
-        switch (param_name)
-        {
-#define PYOPENCL_FIRST_ARG m_program, dev.data() // hackety hack
-          case CL_PROGRAM_BUILD_STATUS:
-            PYOPENCL_GET_INTEGRAL_INFO(ProgramBuild,
-                PYOPENCL_FIRST_ARG, param_name,
-                cl_build_status);
-          case CL_PROGRAM_BUILD_OPTIONS:
-          case CL_PROGRAM_BUILD_LOG:
-            PYOPENCL_GET_STR_INFO(ProgramBuild,
-                PYOPENCL_FIRST_ARG, param_name);
-#if PYOPENCL_CL_VERSION >= 0x1020
-          case CL_PROGRAM_BINARY_TYPE:
-            PYOPENCL_GET_INTEGRAL_INFO(ProgramBuild,
-                PYOPENCL_FIRST_ARG, param_name,
-                cl_program_binary_type);
-#endif
-#undef PYOPENCL_FIRST_ARG
-
-          default:
-            throw error("Program.get_build_info", CL_INVALID_VALUE);
-        }
-      }
-
-      void build(std::string options, py::object py_devices)
-      {
-        PYOPENCL_PARSE_PY_DEVICES;
-
-        PYOPENCL_CALL_GUARDED_THREADED(clBuildProgram,
-            (m_program, num_devices, devices,
-             options.c_str(), 0 ,0));
-      }
-
-#if PYOPENCL_CL_VERSION >= 0x1020
-      void compile(std::string options, py::object py_devices,
-          py::object py_headers)
-      {
-        PYOPENCL_PARSE_PY_DEVICES;
-
-        // {{{ pick apart py_headers
-        // py_headers is a list of tuples *(name, program)*
-
-        std::vector<std::string> header_names;
-        std::vector<cl_program> programs;
-        PYTHON_FOREACH(name_hdr_tup, py_headers)
-        {
-          if (py::len(name_hdr_tup) != 2)
-            throw error("Program.compile", CL_INVALID_VALUE,
-                "epxected (name, header) tuple in headers list");
-          std::string name = py::extract<std::string const &>(name_hdr_tup[0]);
-          program &prg = py::extract<program &>(name_hdr_tup[1]);
-
-          header_names.push_back(name);
-          programs.push_back(prg.data());
-        }
-
-        std::vector<const char *> header_name_ptrs;
-        BOOST_FOREACH(std::string const &name, header_names)
-          header_name_ptrs.push_back(name.c_str());
-
-        // }}}
-
-        PYOPENCL_CALL_GUARDED_THREADED(clCompileProgram,
-            (m_program, num_devices, devices,
-             options.c_str(), header_names.size(),
-             programs.empty() ? NULL : &programs.front(),
-             header_name_ptrs.empty() ? NULL : &header_name_ptrs.front(),
-             0, 0));
-      }
-#endif
-  };
-
-
-
-
-  inline
-  program *create_program_with_source(
-      context &ctx,
-      std::string const &src)
-  {
-    const char *string = src.c_str();
-    size_t length = src.size();
-
-    cl_int status_code;
-    PYOPENCL_PRINT_CALL_TRACE("clCreateProgramWithSource");
-    cl_program result = clCreateProgramWithSource(
-        ctx.data(), 1, &string, &length, &status_code);
-    if (status_code != CL_SUCCESS)
-      throw pyopencl::error("clCreateProgramWithSource", status_code);
-
-    try
-    {
-      return new program(result, false, program::KND_SOURCE);
-    }
-    catch (...)
-    {
-      clReleaseProgram(result);
-      throw;
-    }
-  }
-
-
-
-
-
-  inline
-  program *create_program_with_binary(
-      context &ctx,
-      py::object py_devices,
-      py::object py_binaries)
-  {
-    std::vector<cl_device_id> devices;
-    std::vector<const unsigned char *> binaries;
-    std::vector<size_t> sizes;
-    std::vector<cl_int> binary_statuses;
-
-    int num_devices = len(py_devices);
-    if (len(py_binaries) != num_devices)
-      throw error("create_program_with_binary", CL_INVALID_VALUE,
-          "device and binary counts don't match");
-
-    for (int i = 0; i < num_devices; ++i)
-    {
-      devices.push_back(
-          py::extract<device const &>(py_devices[i])().data());
-      const void *buf;
-      PYOPENCL_BUFFER_SIZE_T len;
-
-      if (PyObject_AsReadBuffer(
-            py::object(py_binaries[i]).ptr(), &buf, &len))
-        throw py::error_already_set();
-
-      binaries.push_back(reinterpret_cast<const unsigned char *>(buf));
-      sizes.push_back(len);
-    }
-
-    binary_statuses.resize(num_devices);
-
-    cl_int status_code;
-    PYOPENCL_PRINT_CALL_TRACE("clCreateProgramWithBinary");
-    cl_program result = clCreateProgramWithBinary(
-        ctx.data(), num_devices,
-        devices.empty( ) ? NULL : &devices.front(),
-        sizes.empty( ) ? NULL : &sizes.front(),
-        binaries.empty( ) ? NULL : &binaries.front(),
-        binary_statuses.empty( ) ? NULL : &binary_statuses.front(),
-        &status_code);
-    if (status_code != CL_SUCCESS)
-      throw pyopencl::error("clCreateProgramWithBinary", status_code);
-
-    /*
-    for (int i = 0; i < num_devices; ++i)
-      printf("%d:%d\n", i, binary_statuses[i]);
-      */
-
-    try
-    {
-      return new program(result, false, program::KND_BINARY);
-    }
-    catch (...)
-    {
-      clReleaseProgram(result);
-      throw;
-    }
-  }
-
-
-
-#if (PYOPENCL_CL_VERSION >= 0x1020) && \
-      ((PYOPENCL_CL_VERSION >= 0x1030) && defined(__APPLE__))
-  inline
-  program *create_program_with_built_in_kernels(
-      context &ctx,
-      py::object py_devices,
-      std::string const &kernel_names)
-  {
-    PYOPENCL_PARSE_PY_DEVICES;
-
-    cl_int status_code;
-    PYOPENCL_PRINT_CALL_TRACE("clCreateProgramWithBuiltInKernels");
-    cl_program result = clCreateProgramWithBuiltInKernels(
-        ctx.data(), num_devices, devices,
-        kernel_names.c_str(), &status_code);
-    if (status_code != CL_SUCCESS)
-      throw pyopencl::error("clCreateProgramWithBuiltInKernels", status_code);
-
-    try
-    {
-      return new program(result, false);
-    }
-    catch (...)
-    {
-      clReleaseProgram(result);
-      throw;
-    }
-  }
-#endif
-
-
-
-#if PYOPENCL_CL_VERSION >= 0x1020
-  inline
-  program *link_program(
-      context &ctx,
-      py::object py_programs,
-      std::string const &options,
-      py::object py_devices
-      )
-  {
-    PYOPENCL_PARSE_PY_DEVICES;
-
-    std::vector<cl_program> programs;
-    PYTHON_FOREACH(py_prg, py_programs)
-    {
-      program &prg = py::extract<program &>(py_prg);
-      programs.push_back(prg.data());
-    }
-
-    cl_int status_code;
-    PYOPENCL_PRINT_CALL_TRACE("clLinkProgram");
-    cl_program result = clLinkProgram(
-        ctx.data(), num_devices, devices,
-        options.c_str(),
-        programs.size(),
-        programs.empty() ? NULL : &programs.front(),
-        0, 0,
-        &status_code);
-
-    if (status_code != CL_SUCCESS)
-      throw pyopencl::error("clLinkPorgram", status_code);
-
-    try
-    {
-      return new program(result, false);
-    }
-    catch (...)
-    {
-      clReleaseProgram(result);
-      throw;
-    }
-  }
-
-#endif
-
-
-#if PYOPENCL_CL_VERSION >= 0x1020
-  inline
-  void unload_platform_compiler(platform &plat)
-  {
-    PYOPENCL_CALL_GUARDED(clUnloadPlatformCompiler, (plat.data()));
-  }
-#endif
-
-  // }}}
-
-  // {{{ kernel
-  class local_memory
-  {
-    private:
-      size_t m_size;
-
-    public:
-      local_memory(size_t size)
-        : m_size(size)
-      { }
-
-      size_t size() const
-      { return m_size; }
-  };
-
-
-
-
-  class kernel : boost::noncopyable
-  {
-    private:
-      cl_kernel m_kernel;
-
-    public:
-      kernel(cl_kernel knl, bool retain)
-        : m_kernel(knl)
-      {
-        if (retain)
-          PYOPENCL_CALL_GUARDED(clRetainKernel, (knl));
-      }
-
-      kernel(program const &prg, std::string const &kernel_name)
-      {
-        cl_int status_code;
-
-        PYOPENCL_PRINT_CALL_TRACE("clCreateKernel");
-        m_kernel = clCreateKernel(prg.data(), kernel_name.c_str(),
-            &status_code);
-        if (status_code != CL_SUCCESS)
-          throw pyopencl::error("clCreateKernel", status_code);
-      }
-
-      ~kernel()
-      {
-        PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseKernel, (m_kernel));
-      }
-
-      cl_kernel data() const
-      {
-        return m_kernel;
-      }
-
-      PYOPENCL_EQUALITY_TESTS(kernel);
-
-      void set_arg_null(cl_uint arg_index)
-      {
-        cl_mem m = 0;
-        PYOPENCL_CALL_GUARDED(clSetKernelArg, (m_kernel, arg_index,
-              sizeof(cl_mem), &m));
-      }
-
-      void set_arg_mem(cl_uint arg_index, memory_object_holder &moh)
-      {
-        cl_mem m = moh.data();
-        PYOPENCL_CALL_GUARDED(clSetKernelArg,
-            (m_kernel, arg_index, sizeof(cl_mem), &m));
-      }
-
-      void set_arg_local(cl_uint arg_index, local_memory const &loc)
-      {
-        PYOPENCL_CALL_GUARDED(clSetKernelArg,
-            (m_kernel, arg_index, loc.size(), 0));
-      }
-
-      void set_arg_sampler(cl_uint arg_index, sampler const &smp)
-      {
-        cl_sampler s = smp.data();
-        PYOPENCL_CALL_GUARDED(clSetKernelArg,
-            (m_kernel, arg_index, sizeof(cl_sampler), &s));
-      }
-
-      void set_arg_buf(cl_uint arg_index, py::object py_buffer)
-      {
-        const void *buf;
-        PYOPENCL_BUFFER_SIZE_T len;
-
-        if (PyObject_AsReadBuffer(py_buffer.ptr(), &buf, &len))
-        {
-          PyErr_Clear();
-          throw error("Kernel.set_arg", CL_INVALID_VALUE,
-              "invalid kernel argument");
-        }
-
-        PYOPENCL_CALL_GUARDED(clSetKernelArg,
-            (m_kernel, arg_index, len, buf));
-      }
-
-      void set_arg(cl_uint arg_index, py::object arg)
-      {
-        if (arg.ptr() == Py_None)
-        {
-          set_arg_null(arg_index);
-          return;
-        }
-
-        py::extract<memory_object_holder &> ex_mo(arg);
-        if (ex_mo.check())
-        {
-          set_arg_mem(arg_index, ex_mo());
-          return;
-        }
-
-        py::extract<local_memory const &> ex_loc(arg);
-        if (ex_loc.check())
-        {
-          set_arg_local(arg_index, ex_loc());
-          return;
-        }
-
-        py::extract<sampler const &> ex_smp(arg);
-        if (ex_smp.check())
-        {
-          set_arg_sampler(arg_index, ex_smp());
-          return;
-        }
-
-        set_arg_buf(arg_index, arg);
-      }
-
-      py::object get_info(cl_kernel_info param_name) const
-      {
-        switch (param_name)
-        {
-          case CL_KERNEL_FUNCTION_NAME:
-            PYOPENCL_GET_STR_INFO(Kernel, m_kernel, param_name);
-          case CL_KERNEL_NUM_ARGS:
-          case CL_KERNEL_REFERENCE_COUNT:
-            PYOPENCL_GET_INTEGRAL_INFO(Kernel, m_kernel, param_name,
-                cl_uint);
-          case CL_KERNEL_CONTEXT:
-            PYOPENCL_GET_OPAQUE_INFO(Kernel, m_kernel, param_name,
-                cl_context, context);
-          case CL_KERNEL_PROGRAM:
-            PYOPENCL_GET_OPAQUE_INFO(Kernel, m_kernel, param_name,
-                cl_program, program);
-#if PYOPENCL_CL_VERSION >= 0x1020
-          case CL_KERNEL_ATTRIBUTES:
-            PYOPENCL_GET_STR_INFO(Kernel, m_kernel, param_name);
-#endif
-          default:
-            throw error("Kernel.get_info", CL_INVALID_VALUE);
-        }
-      }
-
-      py::object get_work_group_info(
-          cl_kernel_work_group_info param_name,
-          device const &dev
-          ) const
-      {
-        switch (param_name)
-        {
-#define PYOPENCL_FIRST_ARG m_kernel, dev.data() // hackety hack
-          case CL_KERNEL_WORK_GROUP_SIZE:
-            PYOPENCL_GET_INTEGRAL_INFO(KernelWorkGroup,
-                PYOPENCL_FIRST_ARG, param_name,
-                size_t);
-          case CL_KERNEL_COMPILE_WORK_GROUP_SIZE:
-            {
-              std::vector<size_t> result;
-              PYOPENCL_GET_VEC_INFO(KernelWorkGroup,
-                  PYOPENCL_FIRST_ARG, param_name, result);
-
-              PYOPENCL_RETURN_VECTOR(size_t, result);
-            }
-          case CL_KERNEL_LOCAL_MEM_SIZE:
-#if PYOPENCL_CL_VERSION >= 0x1010
-          case CL_KERNEL_PRIVATE_MEM_SIZE:
-#endif
-            PYOPENCL_GET_INTEGRAL_INFO(KernelWorkGroup,
-                PYOPENCL_FIRST_ARG, param_name,
-                cl_ulong);
-
-#if PYOPENCL_CL_VERSION >= 0x1010
-          case CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE:
-            PYOPENCL_GET_INTEGRAL_INFO(KernelWorkGroup,
-                PYOPENCL_FIRST_ARG, param_name,
-                size_t);
-#endif
-          default:
-            throw error("Kernel.get_work_group_info", CL_INVALID_VALUE);
-#undef PYOPENCL_FIRST_ARG
-        }
-      }
-
-#if PYOPENCL_CL_VERSION >= 0x1020
-      py::object get_arg_info(
-          cl_uint arg_index,
-          cl_kernel_arg_info param_name
-          ) const
-      {
-        switch (param_name)
-        {
-#define PYOPENCL_FIRST_ARG m_kernel, arg_index // hackety hack
-          case CL_KERNEL_ARG_ADDRESS_QUALIFIER:
-            PYOPENCL_GET_INTEGRAL_INFO(KernelArg,
-                PYOPENCL_FIRST_ARG, param_name,
-                cl_kernel_arg_address_qualifier);
-
-          case CL_KERNEL_ARG_ACCESS_QUALIFIER:
-            PYOPENCL_GET_INTEGRAL_INFO(KernelArg,
-                PYOPENCL_FIRST_ARG, param_name,
-                cl_kernel_arg_access_qualifier);
-
-          case CL_KERNEL_ARG_TYPE_NAME:
-          case CL_KERNEL_ARG_NAME:
-            PYOPENCL_GET_STR_INFO(KernelArg, PYOPENCL_FIRST_ARG, param_name);
-#undef PYOPENCL_FIRST_ARG
-          default:
-            throw error("Kernel.get_arg_info", CL_INVALID_VALUE);
-        }
-      }
-#endif
-  };
-
-
-  inline
-  py::list create_kernels_in_program(program &pgm)
-  {
-    cl_uint num_kernels;
-    PYOPENCL_CALL_GUARDED(clCreateKernelsInProgram, (
-          pgm.data(), 0, 0, &num_kernels));
-
-    std::vector<cl_kernel> kernels(num_kernels);
-    PYOPENCL_CALL_GUARDED(clCreateKernelsInProgram, (
-          pgm.data(), num_kernels,
-          kernels.empty( ) ? NULL : &kernels.front(), &num_kernels));
-
-    py::list result;
-    BOOST_FOREACH(cl_kernel knl, kernels)
-      result.append(handle_from_new_ptr(new kernel(knl, true)));
-
-    return result;
-  }
-
-
-
-  inline
-  event *enqueue_nd_range_kernel(
-      command_queue &cq,
-      kernel &knl,
-      py::object py_global_work_size,
-      py::object py_local_work_size,
-      py::object py_global_work_offset,
-      py::object py_wait_for,
-      bool g_times_l)
-  {
-    PYOPENCL_PARSE_WAIT_FOR;
-
-    cl_uint work_dim = len(py_global_work_size);
-
-    std::vector<size_t> global_work_size;
-    COPY_PY_LIST(size_t, global_work_size);
-
-    size_t *local_work_size_ptr = 0;
-    std::vector<size_t> local_work_size;
-    if (py_local_work_size.ptr() != Py_None)
-    {
-      if (g_times_l)
-        work_dim = std::max(work_dim, unsigned(len(py_local_work_size)));
-      else
-        if (work_dim != unsigned(len(py_local_work_size)))
-          throw error("enqueue_nd_range_kernel", CL_INVALID_VALUE,
-              "global/local work sizes have differing dimensions");
-
-      COPY_PY_LIST(size_t, local_work_size);
-
-      while (local_work_size.size() < work_dim)
-        local_work_size.push_back(1);
-      while (global_work_size.size() < work_dim)
-        global_work_size.push_back(1);
-
-      local_work_size_ptr = local_work_size.empty( ) ? NULL : &local_work_size.front();
-    }
-
-    if (g_times_l && local_work_size_ptr)
-    {
-      for (cl_uint work_axis = 0; work_axis < work_dim; ++work_axis)
-        global_work_size[work_axis] *= local_work_size[work_axis];
-    }
-
-    size_t *global_work_offset_ptr = 0;
-    std::vector<size_t> global_work_offset;
-    if (py_global_work_offset.ptr() != Py_None)
-    {
-      if (work_dim != unsigned(len(py_global_work_offset)))
-        throw error("enqueue_nd_range_kernel", CL_INVALID_VALUE,
-            "global work size and offset have differing dimensions");
-
-      COPY_PY_LIST(size_t, global_work_offset);
-
-      if (g_times_l && local_work_size_ptr)
-      {
-        for (cl_uint work_axis = 0; work_axis < work_dim; ++work_axis)
-          global_work_offset[work_axis] *= local_work_size[work_axis];
-      }
-
-      global_work_offset_ptr = global_work_offset.empty( ) ? NULL :  &global_work_offset.front();
-    }
-
-    PYOPENCL_RETRY_RETURN_IF_MEM_ERROR( {
-          cl_event evt;
-          PYOPENCL_CALL_GUARDED(clEnqueueNDRangeKernel, (
-                cq.data(),
-                knl.data(),
-                work_dim,
-                global_work_offset_ptr,
-                global_work_size.empty( ) ? NULL : &global_work_size.front(),
-                local_work_size_ptr,
-                PYOPENCL_WAITLIST_ARGS, &evt
-                ));
-          PYOPENCL_RETURN_NEW_EVENT(evt);
-        } );
-  }
-
-
-
-
-
-
-  inline
-  event *enqueue_task(
-      command_queue &cq,
-      kernel &knl,
-      py::object py_wait_for)
-  {
-    PYOPENCL_PARSE_WAIT_FOR;
-
-    PYOPENCL_RETRY_RETURN_IF_MEM_ERROR( {
-      cl_event evt;
-      PYOPENCL_CALL_GUARDED(clEnqueueTask, (
-            cq.data(),
-            knl.data(),
-            PYOPENCL_WAITLIST_ARGS, &evt
-            ));
-      PYOPENCL_RETURN_NEW_EVENT(evt);
-    } );
-  }
-
-  // }}}
-
-  // {{{ gl interop
-  inline
-  bool have_gl()
-  {
-#ifdef HAVE_GL
-    return true;
-#else
-    return false;
-#endif
-  }
-
-
-
-
-#ifdef HAVE_GL
-
-#ifdef __APPLE__
-  inline
-  cl_context_properties get_apple_cgl_share_group()
-  {
-    CGLContextObj kCGLContext = CGLGetCurrentContext();
-    CGLShareGroupObj kCGLShareGroup = CGLGetShareGroup(kCGLContext);
-
-    return (cl_context_properties) kCGLShareGroup;
-  }
-#endif /* __APPLE__ */
-
-
-
-
-  class gl_buffer : public memory_object
-  {
-    public:
-      gl_buffer(cl_mem mem, bool retain, py::object *hostbuf=0)
-        : memory_object(mem, retain, hostbuf)
-      { }
-  };
-
-
-
-
-  class gl_renderbuffer : public memory_object
-  {
-    public:
-      gl_renderbuffer(cl_mem mem, bool retain, py::object *hostbuf=0)
-        : memory_object(mem, retain, hostbuf)
-      { }
-  };
-
-
-
-
-  class gl_texture : public image
-  {
-    public:
-      gl_texture(cl_mem mem, bool retain, py::object *hostbuf=0)
-        : image(mem, retain, hostbuf)
-      { }
-
-      py::object get_gl_texture_info(cl_gl_texture_info param_name)
-      {
-        switch (param_name)
-        {
-          case CL_GL_TEXTURE_TARGET:
-            PYOPENCL_GET_INTEGRAL_INFO(GLTexture, data(), param_name, GLenum);
-          case CL_GL_MIPMAP_LEVEL:
-            PYOPENCL_GET_INTEGRAL_INFO(GLTexture, data(), param_name, GLint);
-
-          default:
-            throw error("MemoryObject.get_gl_texture_info", CL_INVALID_VALUE);
-        }
-      }
-  };
-
-
-
-
-#define PYOPENCL_WRAP_BUFFER_CREATOR(TYPE, NAME, CL_NAME, ARGS, CL_ARGS) \
-  inline \
-  TYPE *NAME ARGS \
-  { \
-    cl_int status_code; \
-    PYOPENCL_PRINT_CALL_TRACE(#CL_NAME); \
-    cl_mem mem = CL_NAME CL_ARGS; \
-    \
-    if (status_code != CL_SUCCESS) \
-      throw pyopencl::error(#CL_NAME, status_code); \
-    \
-    try \
-    { \
-      return new TYPE(mem, false); \
-    } \
-    catch (...) \
-    { \
-      PYOPENCL_CALL_GUARDED(clReleaseMemObject, (mem)); \
-      throw; \
-    } \
-  }
-
-
-
-
-  PYOPENCL_WRAP_BUFFER_CREATOR(gl_buffer,
-      create_from_gl_buffer, clCreateFromGLBuffer,
-      (context &ctx, cl_mem_flags flags, GLuint bufobj),
-      (ctx.data(), flags, bufobj, &status_code));
-  PYOPENCL_WRAP_BUFFER_CREATOR(gl_texture,
-      create_from_gl_texture_2d, clCreateFromGLTexture2D,
-      (context &ctx, cl_mem_flags flags,
-         GLenum texture_target, GLint miplevel, GLuint texture),
-      (ctx.data(), flags, texture_target, miplevel, texture, &status_code));
-  PYOPENCL_WRAP_BUFFER_CREATOR(gl_texture,
-      create_from_gl_texture_3d, clCreateFromGLTexture3D,
-      (context &ctx, cl_mem_flags flags,
-         GLenum texture_target, GLint miplevel, GLuint texture),
-      (ctx.data(), flags, texture_target, miplevel, texture, &status_code));
-  PYOPENCL_WRAP_BUFFER_CREATOR(gl_renderbuffer,
-      create_from_gl_renderbuffer, clCreateFromGLRenderbuffer,
-      (context &ctx, cl_mem_flags flags, GLuint renderbuffer),
-      (ctx.data(), flags, renderbuffer, &status_code));
-
-  inline
-  gl_texture *create_from_gl_texture(
-      context &ctx, cl_mem_flags flags,
-      GLenum texture_target, GLint miplevel,
-      GLuint texture, unsigned dims)
-  {
-    if (dims == 2)
-      return create_from_gl_texture_2d(ctx, flags, texture_target, miplevel, texture);
-    else if (dims == 3)
-      return create_from_gl_texture_3d(ctx, flags, texture_target, miplevel, texture);
-    else
-      throw pyopencl::error("Image", CL_INVALID_VALUE,
-          "invalid dimension");
-  }
-
-
-
-
-
-  inline
-  py::tuple get_gl_object_info(memory_object_holder const &mem)
-  {
-    cl_gl_object_type otype;
-    GLuint gl_name;
-    PYOPENCL_CALL_GUARDED(clGetGLObjectInfo, (mem.data(), &otype, &gl_name));
-    return py::make_tuple(otype, gl_name);
-  }
-
-#define WRAP_GL_ENQUEUE(what, What) \
-  inline \
-  event *enqueue_##what##_gl_objects( \
-      command_queue &cq, \
-      py::object py_mem_objects, \
-      py::object py_wait_for) \
-  { \
-    PYOPENCL_PARSE_WAIT_FOR; \
-    \
-    std::vector<cl_mem> mem_objects; \
-    PYTHON_FOREACH(mo, py_mem_objects) \
-      mem_objects.push_back(py::extract<memory_object_holder &>(mo)().data()); \
-    \
-    cl_event evt; \
-    PYOPENCL_CALL_GUARDED(clEnqueue##What##GLObjects, ( \
-          cq.data(), \
-          mem_objects.size(), mem_objects.empty( ) ? NULL : &mem_objects.front(), \
-          PYOPENCL_WAITLIST_ARGS, &evt \
-          )); \
-    \
-    PYOPENCL_RETURN_NEW_EVENT(evt); \
-  }
-
-  WRAP_GL_ENQUEUE(acquire, Acquire);
-  WRAP_GL_ENQUEUE(release, Release);
-#endif
-
-
-
-
-#if defined(cl_khr_gl_sharing) && (cl_khr_gl_sharing >= 1)
-  inline
-  py::object get_gl_context_info_khr(
-      py::object py_properties,
-      cl_gl_context_info param_name,
-      py::object py_platform
-      )
-  {
-    std::vector<cl_context_properties> props
-      = parse_context_properties(py_properties);
-
-    typedef CL_API_ENTRY cl_int (CL_API_CALL
-      *func_ptr_type)(const cl_context_properties * /* properties */,
-          cl_gl_context_info            /* param_name */,
-          size_t                        /* param_value_size */,
-          void *                        /* param_value */,
-          size_t *                      /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
-    func_ptr_type func_ptr;
-
-#if PYOPENCL_CL_VERSION >= 0x1020
-    if (py_platform.ptr() != Py_None)
-    {
-      platform &plat = py::extract<platform &>(py_platform);
-
-      func_ptr = (func_ptr_type) clGetExtensionFunctionAddressForPlatform(
-            plat.data(), "clGetGLContextInfoKHR");
-    }
-    else
-    {
-      PYOPENCL_DEPRECATED("get_gl_context_info_khr with platform=None", "2013.1", );
-
-      func_ptr = (func_ptr_type) clGetExtensionFunctionAddress(
-            "clGetGLContextInfoKHR");
-    }
-#else
-    func_ptr = (func_ptr_type) clGetExtensionFunctionAddress(
-          "clGetGLContextInfoKHR");
-#endif
-
-
-    if (!func_ptr)
-      throw error("Context.get_info", CL_INVALID_PLATFORM,
-          "clGetGLContextInfoKHR extension function not present");
-
-    cl_context_properties *props_ptr
-      = props.empty( ) ? NULL : &props.front();
-
-    switch (param_name)
-    {
-      case CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR:
-        {
-          cl_device_id param_value;
-          PYOPENCL_CALL_GUARDED(func_ptr,
-              (props_ptr, param_name, sizeof(param_value), &param_value, 0));
-          return py::object(handle_from_new_ptr( \
-                new device(param_value, /*retain*/ true)));
-        }
-
-      case CL_DEVICES_FOR_GL_CONTEXT_KHR:
-        {
-          size_t size;
-          PYOPENCL_CALL_GUARDED(func_ptr,
-              (props_ptr, param_name, 0, 0, &size));
-
-          std::vector<cl_device_id> devices;
-
-          devices.resize(size / sizeof(devices.front()));
-
-          PYOPENCL_CALL_GUARDED(func_ptr,
-              (props_ptr, param_name, size,
-               devices.empty( ) ? NULL : &devices.front(), &size));
-
-          py::list result;
-          BOOST_FOREACH(cl_device_id did, devices)
-            result.append(handle_from_new_ptr(
-                  new device(did)));
-
-          return result;
-        }
-
-      default:
-        throw error("get_gl_context_info_khr", CL_INVALID_VALUE);
-    }
-  }
-
-#endif
-
-  // }}}
-
-  // {{{ deferred implementation bits
-
-  inline py::object create_mem_object_wrapper(cl_mem mem)
-  {
-    cl_mem_object_type mem_obj_type;
-    PYOPENCL_CALL_GUARDED(clGetMemObjectInfo, \
-        (mem, CL_MEM_TYPE, sizeof(mem_obj_type), &mem_obj_type, 0));
-
-    switch (mem_obj_type)
-    {
-      case CL_MEM_OBJECT_BUFFER:
-        return py::object(handle_from_new_ptr(
-              new buffer(mem, /*retain*/ true)));
-      case CL_MEM_OBJECT_IMAGE2D:
-      case CL_MEM_OBJECT_IMAGE3D:
-#if PYOPENCL_CL_VERSION >= 0x1020
-      case CL_MEM_OBJECT_IMAGE2D_ARRAY:
-      case CL_MEM_OBJECT_IMAGE1D:
-      case CL_MEM_OBJECT_IMAGE1D_ARRAY:
-      case CL_MEM_OBJECT_IMAGE1D_BUFFER:
-#endif
-        return py::object(handle_from_new_ptr(
-              new image(mem, /*retain*/ true)));
-      default:
-        return py::object(handle_from_new_ptr(
-              new memory_object(mem, /*retain*/ true)));
-    }
-  }
-
-  inline
-  py::object memory_object_from_int(intptr_t cl_mem_as_int)
-  {
-    return create_mem_object_wrapper((cl_mem) cl_mem_as_int);
-  }
-
-
-  inline
-  py::object memory_object_holder::get_info(cl_mem_info param_name) const
-  {
-    switch (param_name)
-    {
-      case CL_MEM_TYPE:
-        PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name,
-            cl_mem_object_type);
-      case CL_MEM_FLAGS:
-        PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name,
-            cl_mem_flags);
-      case CL_MEM_SIZE:
-        PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name,
-            size_t);
-      case CL_MEM_HOST_PTR:
-        throw pyopencl::error("MemoryObject.get_info", CL_INVALID_VALUE,
-            "Use MemoryObject.get_host_array to get host pointer.");
-      case CL_MEM_MAP_COUNT:
-        PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name,
-            cl_uint);
-      case CL_MEM_REFERENCE_COUNT:
-        PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name,
-            cl_uint);
-      case CL_MEM_CONTEXT:
-        PYOPENCL_GET_OPAQUE_INFO(MemObject, data(), param_name,
-            cl_context, context);
-
-#if PYOPENCL_CL_VERSION >= 0x1010
-      case CL_MEM_ASSOCIATED_MEMOBJECT:
-        {
-          cl_mem param_value;
-          PYOPENCL_CALL_GUARDED(clGetMemObjectInfo, \
-              (data(), param_name, sizeof(param_value), &param_value, 0));
-          if (param_value == 0)
-          {
-            // no associated memory object? no problem.
-            return py::object();
-          }
-
-          return create_mem_object_wrapper(param_value);
-        }
-      case CL_MEM_OFFSET:
-        PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name,
-            size_t);
-#endif
-
-      default:
-        throw error("MemoryObjectHolder.get_info", CL_INVALID_VALUE);
-    }
-  }
-
-  inline
-  py::handle<> get_mem_obj_host_array(
-      py::object mem_obj_py,
-      py::object shape, py::object dtype,
-      py::object order_py)
-  {
-    memory_object_holder const &mem_obj =
-      py::extract<memory_object_holder const &>(mem_obj_py);
-    PyArray_Descr *tp_descr;
-    if (PyArray_DescrConverter(dtype.ptr(), &tp_descr) != NPY_SUCCEED)
-      throw py::error_already_set();
-
-    py::extract<npy_intp> shape_as_int(shape);
-    std::vector<npy_intp> dims;
-
-    if (shape_as_int.check())
-      dims.push_back(shape_as_int());
-    else
-      std::copy(
-          py::stl_input_iterator<npy_intp>(shape),
-          py::stl_input_iterator<npy_intp>(),
-          back_inserter(dims));
-
-    NPY_ORDER order = PyArray_CORDER;
-    PyArray_OrderConverter(order_py.ptr(), &order);
-
-    int ary_flags = 0;
-    if (order == PyArray_FORTRANORDER)
-      ary_flags |= NPY_FARRAY;
-    else if (order == PyArray_CORDER)
-      ary_flags |= NPY_CARRAY;
-    else
-      throw std::runtime_error("unrecognized order specifier");
-
-    void *host_ptr;
-    size_t mem_obj_size;
-    PYOPENCL_CALL_GUARDED(clGetMemObjectInfo,
-        (mem_obj.data(), CL_MEM_HOST_PTR, sizeof(host_ptr),
-         &host_ptr, 0));
-    PYOPENCL_CALL_GUARDED(clGetMemObjectInfo,
-        (mem_obj.data(), CL_MEM_SIZE, sizeof(mem_obj_size),
-         &mem_obj_size, 0));
-
-    py::handle<> result = py::handle<>(PyArray_NewFromDescr(
-        &PyArray_Type, tp_descr,
-        dims.size(), &dims.front(), /*strides*/ NULL,
-        host_ptr, ary_flags, /*obj*/NULL));
-
-    if ((size_t) PyArray_NBYTES(result.get()) > mem_obj_size)
-      throw pyopencl::error("MemoryObject.get_host_array",
-          CL_INVALID_VALUE,
-          "Resulting array is larger than memory object.");
-
-    PyArray_BASE(result.get()) = mem_obj_py.ptr();
-    Py_INCREF(mem_obj_py.ptr());
-
-    return result;
-  }
-
-  // }}}
-
-}
-
-
-
-
-#endif
-
-// vim: foldmethod=marker
diff --git a/src/wrapper/wrap_cl_part_1.cpp b/src/wrapper/wrap_cl_part_1.cpp
deleted file mode 100644
index f3448aca..00000000
--- a/src/wrapper/wrap_cl_part_1.cpp
+++ /dev/null
@@ -1,312 +0,0 @@
-#include "wrap_cl.hpp"
-
-
-
-
-using namespace pyopencl;
-
-
-
-
-void pyopencl_expose_part_1()
-{
-  py::docstring_options doc_op;
-  doc_op.disable_cpp_signatures();
-
-  py::def("get_cl_header_version", get_cl_header_version);
-
-  // {{{ platform
-  DEF_SIMPLE_FUNCTION(get_platforms);
-
-  {
-    typedef platform cls;
-    py::class_<cls, boost::noncopyable>("Platform", py::no_init)
-      .DEF_SIMPLE_METHOD(get_info)
-      .def("get_devices", &cls::get_devices,
-          py::arg("device_type")=CL_DEVICE_TYPE_ALL)
-      .def(py::self == py::self)
-      .def(py::self != py::self)
-      .def("__hash__", &cls::hash)
-      PYOPENCL_EXPOSE_TO_FROM_INT_PTR(cl_platform_id)
-      ;
-  }
-
-  // }}}
-
-  // {{{ device
-  {
-    typedef device cls;
-    py::class_<cls, boost::noncopyable>("Device", py::no_init)
-      .DEF_SIMPLE_METHOD(get_info)
-      .def(py::self == py::self)
-      .def(py::self != py::self)
-      .def("__hash__", &cls::hash)
-#if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION)
-      .DEF_SIMPLE_METHOD(create_sub_devices_ext)
-#endif
-#if PYOPENCL_CL_VERSION >= 0x1020
-      .DEF_SIMPLE_METHOD(create_sub_devices)
-#endif
-      PYOPENCL_EXPOSE_TO_FROM_INT_PTR(cl_device_id)
-      ;
-  }
-
-  // }}}
-
-  // {{{ context
-
-  {
-    typedef context cls;
-    py::class_<cls, boost::noncopyable,
-      boost::shared_ptr<cls> >("Context", py::no_init)
-      .def("__init__", make_constructor(create_context,
-            py::default_call_policies(),
-            (py::arg("devices")=py::object(),
-             py::arg("properties")=py::object(),
-             py::arg("dev_type")=py::object()
-            )))
-      .DEF_SIMPLE_METHOD(get_info)
-      .def(py::self == py::self)
-      .def(py::self != py::self)
-      .def("__hash__", &cls::hash)
-      PYOPENCL_EXPOSE_TO_FROM_INT_PTR(cl_context)
-      ;
-  }
-
-  // }}}
-
-  // {{{ command queue
-  {
-    typedef command_queue cls;
-    py::class_<cls, boost::noncopyable>("CommandQueue",
-        py::init<const context &,
-          const device *, cl_command_queue_properties>
-        ((py::arg("context"), py::arg("device")=py::object(), py::arg("properties")=0)))
-      .DEF_SIMPLE_METHOD(get_info)
-#if PYOPENCL_CL_VERSION < 0x1010
-      .DEF_SIMPLE_METHOD(set_property)
-#endif
-      .DEF_SIMPLE_METHOD(flush)
-      .DEF_SIMPLE_METHOD(finish)
-      .def(py::self == py::self)
-      .def(py::self != py::self)
-      .def("__hash__", &cls::hash)
-      PYOPENCL_EXPOSE_TO_FROM_INT_PTR(cl_command_queue)
-      ;
-  }
-
-  // }}}
-
-  // {{{ events/synchronization
-  {
-    typedef event cls;
-    py::class_<cls, boost::noncopyable>("Event", py::no_init)
-      .DEF_SIMPLE_METHOD(get_info)
-      .DEF_SIMPLE_METHOD(get_profiling_info)
-      .DEF_SIMPLE_METHOD(wait)
-      .def(py::self == py::self)
-      .def(py::self != py::self)
-      .def("__hash__", &cls::hash)
-      PYOPENCL_EXPOSE_TO_FROM_INT_PTR(cl_event)
-
-      // deprecated, remove in 2015.x.
-      .def("from_cl_event_as_int", from_int_ptr<cls, cl_event>,
-          py::return_value_policy<py::manage_new_object>())
-      .staticmethod("from_cl_event_as_int")
-      ;
-  }
-  {
-    typedef nanny_event cls;
-    py::class_<cls, boost::noncopyable, py::bases<event> >("NannyEvent", py::no_init)
-      .DEF_SIMPLE_METHOD(get_ward)
-      ;
-  }
-
-  DEF_SIMPLE_FUNCTION(wait_for_events);
-
-#if PYOPENCL_CL_VERSION >= 0x1020
-  py::def("_enqueue_marker_with_wait_list", enqueue_marker_with_wait_list,
-      (py::arg("queue"), py::arg("wait_for")=py::object()),
-      py::return_value_policy<py::manage_new_object>());
-#endif
-  py::def("_enqueue_marker", enqueue_marker,
-      (py::arg("queue")),
-      py::return_value_policy<py::manage_new_object>());
-  py::def("_enqueue_wait_for_events", enqueue_wait_for_events,
-      (py::arg("queue"), py::arg("wait_for")=py::object()));
-
-#if PYOPENCL_CL_VERSION >= 0x1020
-  py::def("_enqueue_barrier_with_wait_list", enqueue_barrier_with_wait_list,
-      (py::arg("queue"), py::arg("wait_for")=py::object()),
-      py::return_value_policy<py::manage_new_object>());
-#endif
-  py::def("_enqueue_barrier", enqueue_barrier, py::arg("queue"));
-
-#if PYOPENCL_CL_VERSION >= 0x1010
-  {
-    typedef user_event cls;
-    py::class_<cls, py::bases<event>, boost::noncopyable>("UserEvent", py::no_init)
-      .def("__init__", make_constructor(
-            create_user_event, py::default_call_policies(), py::args("context")))
-      .DEF_SIMPLE_METHOD(set_status)
-      ;
-  }
-#endif
-
-  // }}}
-
-  // {{{ memory_object
-
-  {
-    typedef memory_object_holder cls;
-    py::class_<cls, boost::noncopyable>(
-        "MemoryObjectHolder", py::no_init)
-      .DEF_SIMPLE_METHOD(get_info)
-      .def("get_host_array", get_mem_obj_host_array,
-          (py::arg("shape"), py::arg("dtype"), py::arg("order")="C"))
-      .def(py::self == py::self)
-      .def(py::self != py::self)
-      .def("__hash__", &cls::hash)
-
-      .add_property("int_ptr", to_int_ptr<cls>,
-          "Return an integer corresponding to the pointer value "
-          "of the underlying :c:type:`cl_mem`. "
-          "Use :meth:`from_int_ptr` to turn back into a Python object."
-          "\n\n.. versionadded:: 2013.2\n")
-      ;
-  }
-  {
-    typedef memory_object cls;
-    py::class_<cls, boost::noncopyable, py::bases<memory_object_holder> >(
-        "MemoryObject", py::no_init)
-      .DEF_SIMPLE_METHOD(release)
-      .add_property("hostbuf", &cls::hostbuf)
-
-      .def("from_int_ptr", memory_object_from_int,
-        "(static method) Return a new Python object referencing the C-level " \
-        ":c:type:`cl_mem` object at the location pointed to " \
-        "by *int_ptr_value*. The relevant :c:func:`clRetain*` function " \
-        "will be called." \
-        "\n\n.. versionadded:: 2013.2\n") \
-      .staticmethod("from_int_ptr")
-
-      // deprecated, remove in 2015.x
-      .def("from_cl_mem_as_int", memory_object_from_int)
-      .staticmethod("from_cl_mem_as_int")
-      ;
-  }
-
-#if PYOPENCL_CL_VERSION >= 0x1020
-  py::def("enqueue_migrate_mem_objects", enqueue_migrate_mem_objects,
-      (py::args("queue", "mem_objects"),
-       py::arg("flags")=0,
-       py::arg("wait_for")=py::object()
-       ),
-      py::return_value_policy<py::manage_new_object>());
-#endif
-
-#ifdef cl_ext_migrate_memobject
-  py::def("enqueue_migrate_mem_object_ext", enqueue_migrate_mem_object_ext,
-      (py::args("queue", "mem_objects"),
-       py::arg("flags")=0,
-       py::arg("wait_for")=py::object()
-       ),
-      py::return_value_policy<py::manage_new_object>());
-#endif
-  // }}}
-
-  // {{{ buffer
-  {
-    typedef buffer cls;
-    py::class_<cls, py::bases<memory_object>, boost::noncopyable>(
-        "Buffer", py::no_init)
-      .def("__init__", make_constructor(create_buffer_py,
-            py::default_call_policies(),
-            (py::args("context", "flags"),
-             py::arg("size")=0,
-             py::arg("hostbuf")=py::object()
-            )))
-#if PYOPENCL_CL_VERSION >= 0x1010
-      .def("get_sub_region", &cls::get_sub_region,
-          (py::args("origin", "size"), py::arg("flags")=0),
-          py::return_value_policy<py::manage_new_object>())
-      .def("__getitem__", &cls::getitem,
-          py::return_value_policy<py::manage_new_object>())
-#endif
-      ;
-  }
-
-  // }}}
-
-  // {{{ transfers
-
-  // {{{ byte-for-byte
-  py::def("_enqueue_read_buffer", enqueue_read_buffer,
-      (py::args("queue", "mem", "hostbuf"),
-       py::arg("device_offset")=0,
-       py::arg("wait_for")=py::object(),
-       py::arg("is_blocking")=true
-       ),
-      py::return_value_policy<py::manage_new_object>());
-  py::def("_enqueue_write_buffer", enqueue_write_buffer,
-      (py::args("queue", "mem", "hostbuf"),
-       py::arg("device_offset")=0,
-       py::arg("wait_for")=py::object(),
-       py::arg("is_blocking")=true
-       ),
-      py::return_value_policy<py::manage_new_object>());
-  py::def("_enqueue_copy_buffer", enqueue_copy_buffer,
-      (py::args("queue", "src", "dst"),
-       py::arg("byte_count")=-1,
-       py::arg("src_offset")=0,
-       py::arg("dst_offset")=0,
-       py::arg("wait_for")=py::object()
-       ),
-      py::return_value_policy<py::manage_new_object>());
-
-  // }}}
-
-  // {{{ rectangular
-
-#if PYOPENCL_CL_VERSION >= 0x1010
-  py::def("_enqueue_read_buffer_rect", enqueue_read_buffer_rect,
-      (py::args("queue", "mem", "hostbuf",
-                "buffer_origin", "host_origin", "region"),
-       py::arg("buffer_pitches")=py::object(),
-       py::arg("host_pitches")=py::object(),
-       py::arg("wait_for")=py::object(),
-       py::arg("is_blocking")=true
-       ),
-      py::return_value_policy<py::manage_new_object>());
-  py::def("_enqueue_write_buffer_rect", enqueue_write_buffer_rect,
-      (py::args("queue", "mem", "hostbuf",
-                "buffer_origin", "host_origin", "region"),
-       py::arg("buffer_pitches")=py::object(),
-       py::arg("host_pitches")=py::object(),
-       py::arg("wait_for")=py::object(),
-       py::arg("is_blocking")=true
-       ),
-      py::return_value_policy<py::manage_new_object>());
-  py::def("_enqueue_copy_buffer_rect", enqueue_copy_buffer_rect,
-      (py::args("queue", "src", "dst",
-                "src_origin", "dst_origin", "region"),
-       py::arg("src_pitches")=py::object(),
-       py::arg("dst_pitches")=py::object(),
-       py::arg("wait_for")=py::object()
-       ),
-      py::return_value_policy<py::manage_new_object>());
-#endif
-
-  // }}}
-
-  // }}}
-
-#if PYOPENCL_CL_VERSION >= 0x1020
-  py::def("_enqueue_fill_buffer", enqueue_fill_buffer,
-      (py::args("queue", "mem", "pattern", "offset", "size"),
-       py::arg("wait_for")=py::object()),
-      py::return_value_policy<py::manage_new_object>());
-#endif
-}
-
-// vim: foldmethod=marker
diff --git a/src/wrapper/wrap_cl_part_2.cpp b/src/wrapper/wrap_cl_part_2.cpp
deleted file mode 100644
index 4d010796..00000000
--- a/src/wrapper/wrap_cl_part_2.cpp
+++ /dev/null
@@ -1,359 +0,0 @@
-#include "wrap_cl.hpp"
-
-
-
-
-namespace pyopencl {
-#if PYOPENCL_CL_VERSION >= 0x1020
-  py::object image_desc_dummy_getter(cl_image_desc &desc)
-  {
-    return py::object();
-  }
-
-  void image_desc_set_shape(cl_image_desc &desc, py::object py_shape)
-  {
-    COPY_PY_REGION_TRIPLE(shape);
-    desc.image_width = shape[0];
-    desc.image_height = shape[1];
-    desc.image_depth = shape[2];
-    desc.image_array_size = shape[2];
-  }
-
-  void image_desc_set_pitches(cl_image_desc &desc, py::object py_pitches)
-  {
-    COPY_PY_PITCH_TUPLE(pitches);
-    desc.image_row_pitch = pitches[0];
-    desc.image_slice_pitch = pitches[1];
-  }
-
-  void image_desc_set_buffer(cl_image_desc &desc, memory_object *mobj)
-  {
-    if (mobj)
-      desc.buffer = mobj->data();
-    else
-      desc.buffer = 0;
-  }
-
-#endif
-}
-
-
-
-
-using namespace pyopencl;
-
-
-
-
-void pyopencl_expose_part_2()
-{
-  py::docstring_options doc_op;
-  doc_op.disable_cpp_signatures();
-
-  // {{{ image
-
-#if PYOPENCL_CL_VERSION >= 0x1020
-  {
-    typedef cl_image_desc cls;
-    py::class_<cls>("ImageDescriptor")
-      .def_readwrite("image_type", &cls::image_type)
-      .add_property("shape", &image_desc_dummy_getter, image_desc_set_shape)
-      .def_readwrite("array_size", &cls::image_array_size)
-      .add_property("pitches", &image_desc_dummy_getter, image_desc_set_pitches)
-      .def_readwrite("num_mip_levels", &cls::num_mip_levels)
-      .def_readwrite("num_samples", &cls::num_samples)
-      .add_property("buffer", &image_desc_dummy_getter, image_desc_set_buffer)
-      ;
-  }
-#endif
-
-  {
-    typedef image cls;
-    py::class_<cls, py::bases<memory_object>, boost::noncopyable>(
-        "Image", py::no_init)
-      .def("__init__", make_constructor(create_image,
-            py::default_call_policies(),
-            (py::args("context", "flags", "format"),
-             py::arg("shape")=py::object(),
-             py::arg("pitches")=py::object(),
-             py::arg("hostbuf")=py::object()
-            )))
-#if PYOPENCL_CL_VERSION >= 0x1020
-      .def("__init__", make_constructor(create_image_from_desc,
-            py::default_call_policies(),
-            (py::args("context", "flags", "format", "desc"),
-             py::arg("hostbuf")=py::object())))
-#endif
-      .DEF_SIMPLE_METHOD(get_image_info)
-      ;
-  }
-
-  {
-    typedef cl_image_format cls;
-    py::class_<cls>("ImageFormat")
-      .def("__init__", py::make_constructor(make_image_format))
-      .def_readwrite("channel_order", &cls::image_channel_order)
-      .def_readwrite("channel_data_type", &cls::image_channel_data_type)
-      .add_property("channel_count", &get_image_format_channel_count)
-      .add_property("dtype_size", &get_image_format_channel_dtype_size)
-      .add_property("itemsize", &get_image_format_item_size)
-      ;
-  }
-
-  DEF_SIMPLE_FUNCTION(get_supported_image_formats);
-
-  py::def("_enqueue_read_image", enqueue_read_image,
-      (py::args("queue", "mem", "origin", "region", "hostbuf"),
-       py::arg("row_pitch")=0,
-       py::arg("slice_pitch")=0,
-       py::arg("wait_for")=py::object(),
-       py::arg("is_blocking")=true
-       ),
-      py::return_value_policy<py::manage_new_object>());
-  py::def("_enqueue_write_image", enqueue_write_image,
-      (py::args("queue", "mem", "origin", "region", "hostbuf"),
-       py::arg("row_pitch")=0,
-       py::arg("slice_pitch")=0,
-       py::arg("wait_for")=py::object(),
-       py::arg("is_blocking")=true
-       ),
-      py::return_value_policy<py::manage_new_object>());
-
-  py::def("_enqueue_copy_image", enqueue_copy_image,
-      (py::args("queue", "src", "dest", "src_origin", "dest_origin", "region"),
-       py::arg("wait_for")=py::object()),
-      py::return_value_policy<py::manage_new_object>());
-  py::def("_enqueue_copy_image_to_buffer", enqueue_copy_image_to_buffer,
-      (py::args("queue", "src", "dest", "origin", "region", "offset"),
-       py::arg("wait_for")=py::object()),
-      py::return_value_policy<py::manage_new_object>());
-  py::def("_enqueue_copy_buffer_to_image", enqueue_copy_buffer_to_image,
-      (py::args("queue", "src", "dest", "offset", "origin", "region"),
-       py::arg("wait_for")=py::object()),
-      py::return_value_policy<py::manage_new_object>());
-
-#if PYOPENCL_CL_VERSION >= 0x1020
-  py::def("enqueue_fill_image", enqueue_write_image,
-      (py::args("queue", "mem", "color", "origin", "region"),
-       py::arg("wait_for")=py::object()),
-      py::return_value_policy<py::manage_new_object>());
-#endif
-
-  // }}}
-
-  // {{{ memory_map
-  {
-    typedef memory_map cls;
-    py::class_<cls, boost::noncopyable>("MemoryMap", py::no_init)
-      .def("release", &cls::release,
-          (py::arg("queue")=0, py::arg("wait_for")=py::object()),
-          py::return_value_policy<py::manage_new_object>())
-      ;
-  }
-
-  py::def("enqueue_map_buffer", enqueue_map_buffer,
-      (py::args("queue", "buf", "flags",
-                "offset",
-                "shape", "dtype"),
-       py::arg("order")="C",
-       py::arg("strides")=py::object(),
-       py::arg("wait_for")=py::object(),
-       py::arg("is_blocking")=true));
-  py::def("enqueue_map_image", enqueue_map_image,
-      (py::args("queue", "img", "flags",
-                "origin", "region",
-                "shape", "dtype"),
-       py::arg("order")="C",
-       py::arg("strides")=py::object(),
-       py::arg("wait_for")=py::object(),
-       py::arg("is_blocking")=true));
-
-  // }}}
-
-  // {{{ sampler
-  {
-    typedef sampler cls;
-    py::class_<cls, boost::noncopyable>("Sampler",
-        py::init<context const &, bool, cl_addressing_mode, cl_filter_mode>())
-      .DEF_SIMPLE_METHOD(get_info)
-      .def(py::self == py::self)
-      .def(py::self != py::self)
-      .def("__hash__", &cls::hash)
-      PYOPENCL_EXPOSE_TO_FROM_INT_PTR(cl_sampler)
-      ;
-  }
-
-  // }}}
-
-  // {{{ program
-  {
-    typedef program cls;
-    py::enum_<cls::program_kind_type>("program_kind")
-      .value("UNKNOWN", cls::KND_UNKNOWN)
-      .value("SOURCE", cls::KND_SOURCE)
-      .value("BINARY", cls::KND_BINARY)
-      ;
-
-    py::class_<cls, boost::noncopyable>("_Program", py::no_init)
-      .def("__init__", make_constructor(
-            create_program_with_source,
-            py::default_call_policies(),
-            py::args("context", "src")))
-      .def("__init__", make_constructor(
-            create_program_with_binary,
-            py::default_call_policies(),
-            py::args("context", "devices", "binaries")))
-#if (PYOPENCL_CL_VERSION >= 0x1020) && \
-      ((PYOPENCL_CL_VERSION >= 0x1030) && defined(__APPLE__))
-      .def("create_with_built_in_kernels",
-          create_program_with_built_in_kernels,
-          py::args("context", "devices", "kernel_names"),
-          py::return_value_policy<py::manage_new_object>())
-      .staticmethod("create_with_built_in_kernels")
-#endif
-      .DEF_SIMPLE_METHOD(kind)
-      .DEF_SIMPLE_METHOD(get_info)
-      .DEF_SIMPLE_METHOD(get_build_info)
-      .def("_build", &cls::build,
-          (py::arg("options")="", py::arg("devices")=py::object()))
-#if PYOPENCL_CL_VERSION >= 0x1020
-      .def("compile", &cls::compile,
-          (py::arg("options")="", py::arg("devices")=py::object(),
-           py::arg("headers")=py::list()))
-      .def("link", &link_program,
-          (py::arg("context"),
-           py::arg("programs"),
-           py::arg("options")="",
-           py::arg("devices")=py::object()),
-          py::return_value_policy<py::manage_new_object>())
-      .staticmethod("link")
-#endif
-      .def(py::self == py::self)
-      .def(py::self != py::self)
-      .def("__hash__", &cls::hash)
-      .def("all_kernels", create_kernels_in_program)
-      PYOPENCL_EXPOSE_TO_FROM_INT_PTR(cl_program)
-      ;
-  }
-
-#if PYOPENCL_CL_VERSION >= 0x1020
-  py::def("unload_platform_compiler", unload_platform_compiler);
-#endif
-
-  // }}}
-
-  // {{{ kernel
-
-  {
-    typedef kernel cls;
-    py::class_<cls, boost::noncopyable>("Kernel",
-        py::init<const program &, std::string const &>())
-      .DEF_SIMPLE_METHOD(get_info)
-      .DEF_SIMPLE_METHOD(get_work_group_info)
-      .DEF_SIMPLE_METHOD(set_arg)
-#if PYOPENCL_CL_VERSION >= 0x1020
-      .DEF_SIMPLE_METHOD(get_arg_info)
-#endif
-      .def(py::self == py::self)
-      .def(py::self != py::self)
-      .def("__hash__", &cls::hash)
-      PYOPENCL_EXPOSE_TO_FROM_INT_PTR(cl_kernel)
-      ;
-  }
-
-  {
-    typedef local_memory cls;
-    py::class_<cls, boost::noncopyable>("LocalMemory",
-        py::init<size_t>(py::arg("size")))
-      .add_property("size", &cls::size)
-      ;
-  }
-
-
-  py::def("enqueue_nd_range_kernel", enqueue_nd_range_kernel,
-      (py::args("queue", "kernel"),
-      py::arg("global_work_size"),
-      py::arg("local_work_size"),
-      py::arg("global_work_offset")=py::object(),
-      py::arg("wait_for")=py::object(),
-      py::arg("g_times_l")=false
-      ),
-      py::return_value_policy<py::manage_new_object>());
-  py::def("enqueue_task", enqueue_task,
-      (py::args("queue", "kernel"),
-      py::arg("wait_for")=py::object()
-      ),
-      py::return_value_policy<py::manage_new_object>());
-
-  // TODO: clEnqueueNativeKernel
-  // }}}
-
-  // {{{ GL interop
-  DEF_SIMPLE_FUNCTION(have_gl);
-
-#ifdef HAVE_GL
-
-#ifdef __APPLE__
-  DEF_SIMPLE_FUNCTION(get_apple_cgl_share_group);
-#endif /* __APPLE__ */
-
-  {
-    typedef gl_buffer cls;
-    py::class_<cls, py::bases<memory_object>, boost::noncopyable>(
-        "GLBuffer", py::no_init)
-      .def("__init__", make_constructor(create_from_gl_buffer,
-            py::default_call_policies(),
-            (py::args("context", "flags", "bufobj"))))
-      .def("get_gl_object_info", get_gl_object_info)
-      ;
-  }
-
-  {
-    typedef gl_renderbuffer cls;
-    py::class_<cls, py::bases<memory_object>, boost::noncopyable>(
-        "GLRenderBuffer", py::no_init)
-      .def("__init__", make_constructor(create_from_gl_renderbuffer,
-            py::default_call_policies(),
-            (py::args("context", "flags", "bufobj"))))
-      .def("get_gl_object_info", get_gl_object_info)
-      ;
-  }
-
-  {
-    typedef gl_texture cls;
-    py::class_<cls, py::bases<image>, boost::noncopyable>(
-        "GLTexture", py::no_init)
-      .def("__init__", make_constructor(create_from_gl_texture,
-            py::default_call_policies(),
-            (py::args("context", "flags",
-                      "texture_target", "miplevel",
-                      "texture", "dims"))))
-      .def("get_gl_object_info", get_gl_object_info)
-      .DEF_SIMPLE_METHOD(get_gl_texture_info)
-      ;
-  }
-
-  py::def("enqueue_acquire_gl_objects", enqueue_acquire_gl_objects,
-      (py::args("queue", "mem_objects"),
-      py::arg("wait_for")=py::object()
-      ),
-      py::return_value_policy<py::manage_new_object>());
-  py::def("enqueue_release_gl_objects", enqueue_release_gl_objects,
-      (py::args("queue", "mem_objects"),
-      py::arg("wait_for")=py::object()
-      ),
-      py::return_value_policy<py::manage_new_object>());
-
-#if defined(cl_khr_gl_sharing) && (cl_khr_gl_sharing >= 1)
-  py::def("get_gl_context_info_khr", get_gl_context_info_khr,
-      (py::args("properties", "param_name"), py::arg("platform")=py::object()));
-#endif
-
-#endif
-  // }}}
-}
-
-
-
-
-// vim: foldmethod=marker
diff --git a/src/wrapper/wrap_constants.cpp b/src/wrapper/wrap_constants.cpp
deleted file mode 100644
index 64511d01..00000000
--- a/src/wrapper/wrap_constants.cpp
+++ /dev/null
@@ -1,868 +0,0 @@
-#include "wrap_cl.hpp"
-
-
-
-
-using namespace pyopencl;
-
-
-
-
-namespace
-{
-  py::handle<>
-    CLError,
-    CLMemoryError,
-    CLLogicError,
-    CLRuntimeError;
-
-
-
-
-  void translate_cl_error(const error &err)
-  {
-    if (err.code() == CL_MEM_OBJECT_ALLOCATION_FAILURE)
-      PyErr_SetObject(CLMemoryError.get(), py::object(err).ptr());
-    else if (err.code() <= CL_INVALID_VALUE)
-      PyErr_SetObject(CLLogicError.get(), py::object(err).ptr());
-    else if (err.code() > CL_INVALID_VALUE && err.code() < CL_SUCCESS)
-      PyErr_SetObject(CLRuntimeError.get(), py::object(err).ptr());
-    else
-      PyErr_SetObject(CLError.get(), py::object(err).ptr());
-  }
-
-
-
-
-  // {{{ 'fake' constant scopes
-  class status_code { };
-  class platform_info { };
-  class device_type { };
-  class device_info { };
-  class device_fp_config { };
-  class device_mem_cache_type { };
-  class device_local_mem_type { };
-  class device_exec_capabilities { };
-  class command_queue_properties { };
-  class context_info { };
-  class gl_context_info { };
-  class context_properties { };
-  class command_queue_info { };
-  class mem_flags { };
-  class channel_order { };
-  class channel_type { };
-  class mem_object_type { };
-  class mem_info { };
-  class image_info { };
-  class addressing_mode { };
-  class filter_mode { };
-  class sampler_info { };
-  class map_flags { };
-  class program_info { };
-  class program_build_info { };
-  class program_binary_type { };
-  class build_status { };
-  class kernel_info { };
-  class kernel_arg_info { };
-  class kernel_arg_address_qualifier { };
-  class kernel_arg_access_qualifier { };
-  class kernel_work_group_info { };
-  class event_info { };
-  class command_type { };
-  class command_execution_status { };
-  class profiling_info { };
-  class buffer_create_type { };
-  class mem_migration_flags { };
-
-  class device_partition_property { };
-  class device_affinity_domain { };
-
-  class device_partition_property_ext { };
-  class affinity_domain_ext { };
-
-  class gl_object_type { };
-  class gl_texture_info { };
-
-  class migrate_mem_object_flags_ext {};
-  // }}}
-}
-
-
-
-
-void pyopencl_expose_constants()
-{
-  // {{{ exceptions
-#define DECLARE_EXC(NAME, BASE) \
-  CL##NAME = py::handle<>(PyErr_NewException("pyopencl." #NAME, BASE, NULL)); \
-  py::scope().attr(#NAME) = CL##NAME;
-
-  {
-    DECLARE_EXC(Error, NULL);
-    DECLARE_EXC(MemoryError, CLError.get());
-    DECLARE_EXC(LogicError, CLError.get());
-    DECLARE_EXC(RuntimeError, CLError.get());
-
-    py::register_exception_translator<error>(translate_cl_error);
-  }
-  // }}}
-
-  // {{{ constants
-#define ADD_ATTR(PREFIX, NAME) \
-  cls.attr(#NAME) = CL_##PREFIX##NAME
-#define ADD_ATTR_SUFFIX(PREFIX, NAME, SUFFIX) \
-  cls.attr(#NAME) = CL_##PREFIX##NAME##SUFFIX
-
-  {
-    typedef error cls;
-    py::class_<error> ("_error", py::no_init)
-      .DEF_SIMPLE_METHOD(routine)
-      .DEF_SIMPLE_METHOD(code)
-      .DEF_SIMPLE_METHOD(what)
-      ;
-  }
-
-  {
-    py::class_<status_code> cls("status_code", py::no_init);
-
-    ADD_ATTR(, SUCCESS);
-    ADD_ATTR(, DEVICE_NOT_FOUND);
-    ADD_ATTR(, DEVICE_NOT_AVAILABLE);
-#if !(defined(CL_PLATFORM_NVIDIA) && CL_PLATFORM_NVIDIA == 0x3001)
-    ADD_ATTR(, COMPILER_NOT_AVAILABLE);
-#endif
-    ADD_ATTR(, MEM_OBJECT_ALLOCATION_FAILURE);
-    ADD_ATTR(, OUT_OF_RESOURCES);
-    ADD_ATTR(, OUT_OF_HOST_MEMORY);
-    ADD_ATTR(, PROFILING_INFO_NOT_AVAILABLE);
-    ADD_ATTR(, MEM_COPY_OVERLAP);
-    ADD_ATTR(, IMAGE_FORMAT_MISMATCH);
-    ADD_ATTR(, IMAGE_FORMAT_NOT_SUPPORTED);
-    ADD_ATTR(, BUILD_PROGRAM_FAILURE);
-    ADD_ATTR(, MAP_FAILURE);
-
-    ADD_ATTR(, INVALID_VALUE);
-    ADD_ATTR(, INVALID_DEVICE_TYPE);
-    ADD_ATTR(, INVALID_PLATFORM);
-    ADD_ATTR(, INVALID_DEVICE);
-    ADD_ATTR(, INVALID_CONTEXT);
-    ADD_ATTR(, INVALID_QUEUE_PROPERTIES);
-    ADD_ATTR(, INVALID_COMMAND_QUEUE);
-    ADD_ATTR(, INVALID_HOST_PTR);
-    ADD_ATTR(, INVALID_MEM_OBJECT);
-    ADD_ATTR(, INVALID_IMAGE_FORMAT_DESCRIPTOR);
-    ADD_ATTR(, INVALID_IMAGE_SIZE);
-    ADD_ATTR(, INVALID_SAMPLER);
-    ADD_ATTR(, INVALID_BINARY);
-    ADD_ATTR(, INVALID_BUILD_OPTIONS);
-    ADD_ATTR(, INVALID_PROGRAM);
-    ADD_ATTR(, INVALID_PROGRAM_EXECUTABLE);
-    ADD_ATTR(, INVALID_KERNEL_NAME);
-    ADD_ATTR(, INVALID_KERNEL_DEFINITION);
-    ADD_ATTR(, INVALID_KERNEL);
-    ADD_ATTR(, INVALID_ARG_INDEX);
-    ADD_ATTR(, INVALID_ARG_VALUE);
-    ADD_ATTR(, INVALID_ARG_SIZE);
-    ADD_ATTR(, INVALID_KERNEL_ARGS);
-    ADD_ATTR(, INVALID_WORK_DIMENSION);
-    ADD_ATTR(, INVALID_WORK_GROUP_SIZE);
-    ADD_ATTR(, INVALID_WORK_ITEM_SIZE);
-    ADD_ATTR(, INVALID_GLOBAL_OFFSET);
-    ADD_ATTR(, INVALID_EVENT_WAIT_LIST);
-    ADD_ATTR(, INVALID_EVENT);
-    ADD_ATTR(, INVALID_OPERATION);
-    ADD_ATTR(, INVALID_GL_OBJECT);
-    ADD_ATTR(, INVALID_BUFFER_SIZE);
-    ADD_ATTR(, INVALID_MIP_LEVEL);
-
-#if defined(cl_khr_icd) && (cl_khr_icd >= 1)
-    ADD_ATTR(, PLATFORM_NOT_FOUND_KHR);
-#endif
-
-#if defined(cl_khr_gl_sharing) && (cl_khr_gl_sharing >= 1)
-    ADD_ATTR(, INVALID_GL_SHAREGROUP_REFERENCE_KHR);
-#endif
-
-#if PYOPENCL_CL_VERSION >= 0x1010
-    ADD_ATTR(, MISALIGNED_SUB_BUFFER_OFFSET);
-    ADD_ATTR(, EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST);
-    ADD_ATTR(, INVALID_GLOBAL_WORK_SIZE);
-#endif
-
-#if PYOPENCL_CL_VERSION >= 0x1020
-    ADD_ATTR(, COMPILE_PROGRAM_FAILURE);
-    ADD_ATTR(, LINKER_NOT_AVAILABLE);
-    ADD_ATTR(, LINK_PROGRAM_FAILURE);
-    ADD_ATTR(, DEVICE_PARTITION_FAILED);
-    ADD_ATTR(, KERNEL_ARG_INFO_NOT_AVAILABLE);
-    ADD_ATTR(, INVALID_IMAGE_DESCRIPTOR);
-    ADD_ATTR(, INVALID_COMPILER_OPTIONS);
-    ADD_ATTR(, INVALID_LINKER_OPTIONS);
-    ADD_ATTR(, INVALID_DEVICE_PARTITION_COUNT);
-#endif
-
-#if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION)
-    ADD_ATTR(, DEVICE_PARTITION_FAILED_EXT);
-    ADD_ATTR(, INVALID_PARTITION_COUNT_EXT);
-    ADD_ATTR(, INVALID_PARTITION_NAME_EXT);
-#endif
-  }
-
-  {
-    py::class_<platform_info> cls("platform_info", py::no_init);
-    ADD_ATTR(PLATFORM_, PROFILE);
-    ADD_ATTR(PLATFORM_, VERSION);
-    ADD_ATTR(PLATFORM_, NAME);
-    ADD_ATTR(PLATFORM_, VENDOR);
-#if !(defined(CL_PLATFORM_NVIDIA) && CL_PLATFORM_NVIDIA == 0x3001)
-    ADD_ATTR(PLATFORM_, EXTENSIONS);
-#endif
-  }
-
-  {
-    py::class_<device_type> cls("device_type", py::no_init);
-    ADD_ATTR(DEVICE_TYPE_, DEFAULT);
-    ADD_ATTR(DEVICE_TYPE_, CPU);
-    ADD_ATTR(DEVICE_TYPE_, GPU);
-    ADD_ATTR(DEVICE_TYPE_, ACCELERATOR);
-#if PYOPENCL_CL_VERSION >= 0x1020
-    ADD_ATTR(DEVICE_TYPE_, CUSTOM);
-#endif
-    ADD_ATTR(DEVICE_TYPE_, ALL);
-  }
-
-  {
-    py::class_<device_info> cls("device_info", py::no_init);
-    ADD_ATTR(DEVICE_, TYPE);
-    ADD_ATTR(DEVICE_, VENDOR_ID);
-    ADD_ATTR(DEVICE_, MAX_COMPUTE_UNITS);
-    ADD_ATTR(DEVICE_, MAX_WORK_ITEM_DIMENSIONS);
-    ADD_ATTR(DEVICE_, MAX_WORK_GROUP_SIZE);
-    ADD_ATTR(DEVICE_, MAX_WORK_ITEM_SIZES);
-    ADD_ATTR(DEVICE_, PREFERRED_VECTOR_WIDTH_CHAR);
-    ADD_ATTR(DEVICE_, PREFERRED_VECTOR_WIDTH_SHORT);
-    ADD_ATTR(DEVICE_, PREFERRED_VECTOR_WIDTH_INT);
-    ADD_ATTR(DEVICE_, PREFERRED_VECTOR_WIDTH_LONG);
-    ADD_ATTR(DEVICE_, PREFERRED_VECTOR_WIDTH_FLOAT);
-    ADD_ATTR(DEVICE_, PREFERRED_VECTOR_WIDTH_DOUBLE);
-    ADD_ATTR(DEVICE_, MAX_CLOCK_FREQUENCY);
-    ADD_ATTR(DEVICE_, ADDRESS_BITS);
-    ADD_ATTR(DEVICE_, MAX_READ_IMAGE_ARGS);
-    ADD_ATTR(DEVICE_, MAX_WRITE_IMAGE_ARGS);
-    ADD_ATTR(DEVICE_, MAX_MEM_ALLOC_SIZE);
-    ADD_ATTR(DEVICE_, IMAGE2D_MAX_WIDTH);
-    ADD_ATTR(DEVICE_, IMAGE2D_MAX_HEIGHT);
-    ADD_ATTR(DEVICE_, IMAGE3D_MAX_WIDTH);
-    ADD_ATTR(DEVICE_, IMAGE3D_MAX_HEIGHT);
-    ADD_ATTR(DEVICE_, IMAGE3D_MAX_DEPTH);
-    ADD_ATTR(DEVICE_, IMAGE_SUPPORT);
-    ADD_ATTR(DEVICE_, MAX_PARAMETER_SIZE);
-    ADD_ATTR(DEVICE_, MAX_SAMPLERS);
-    ADD_ATTR(DEVICE_, MEM_BASE_ADDR_ALIGN);
-    ADD_ATTR(DEVICE_, MIN_DATA_TYPE_ALIGN_SIZE);
-    ADD_ATTR(DEVICE_, SINGLE_FP_CONFIG);
-#ifdef CL_DEVICE_DOUBLE_FP_CONFIG
-    ADD_ATTR(DEVICE_, DOUBLE_FP_CONFIG);
-#endif
-#ifdef CL_DEVICE_HALF_FP_CONFIG
-    ADD_ATTR(DEVICE_, HALF_FP_CONFIG);
-#endif
-    ADD_ATTR(DEVICE_, GLOBAL_MEM_CACHE_TYPE);
-    ADD_ATTR(DEVICE_, GLOBAL_MEM_CACHELINE_SIZE);
-    ADD_ATTR(DEVICE_, GLOBAL_MEM_CACHE_SIZE);
-    ADD_ATTR(DEVICE_, GLOBAL_MEM_SIZE);
-    ADD_ATTR(DEVICE_, MAX_CONSTANT_BUFFER_SIZE);
-    ADD_ATTR(DEVICE_, MAX_CONSTANT_ARGS);
-    ADD_ATTR(DEVICE_, LOCAL_MEM_TYPE);
-    ADD_ATTR(DEVICE_, LOCAL_MEM_SIZE);
-    ADD_ATTR(DEVICE_, ERROR_CORRECTION_SUPPORT);
-    ADD_ATTR(DEVICE_, PROFILING_TIMER_RESOLUTION);
-    ADD_ATTR(DEVICE_, ENDIAN_LITTLE);
-    ADD_ATTR(DEVICE_, AVAILABLE);
-    ADD_ATTR(DEVICE_, COMPILER_AVAILABLE);
-    ADD_ATTR(DEVICE_, EXECUTION_CAPABILITIES);
-    ADD_ATTR(DEVICE_, QUEUE_PROPERTIES);
-    ADD_ATTR(DEVICE_, NAME);
-    ADD_ATTR(DEVICE_, VENDOR);
-    ADD_ATTR(, DRIVER_VERSION);
-    ADD_ATTR(DEVICE_, VERSION);
-    ADD_ATTR(DEVICE_, PROFILE);
-    ADD_ATTR(DEVICE_, VERSION);
-    ADD_ATTR(DEVICE_, EXTENSIONS);
-    ADD_ATTR(DEVICE_, PLATFORM);
-#if PYOPENCL_CL_VERSION >= 0x1010
-    ADD_ATTR(DEVICE_, PREFERRED_VECTOR_WIDTH_HALF);
-    ADD_ATTR(DEVICE_, HOST_UNIFIED_MEMORY);
-    ADD_ATTR(DEVICE_, NATIVE_VECTOR_WIDTH_CHAR);
-    ADD_ATTR(DEVICE_, NATIVE_VECTOR_WIDTH_SHORT);
-    ADD_ATTR(DEVICE_, NATIVE_VECTOR_WIDTH_INT);
-    ADD_ATTR(DEVICE_, NATIVE_VECTOR_WIDTH_LONG);
-    ADD_ATTR(DEVICE_, NATIVE_VECTOR_WIDTH_FLOAT);
-    ADD_ATTR(DEVICE_, NATIVE_VECTOR_WIDTH_DOUBLE);
-    ADD_ATTR(DEVICE_, NATIVE_VECTOR_WIDTH_HALF);
-    ADD_ATTR(DEVICE_, OPENCL_C_VERSION);
-#endif
-// support for cl_nv_device_attribute_query
-#ifdef CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV
-    ADD_ATTR(DEVICE_, COMPUTE_CAPABILITY_MAJOR_NV);
-    ADD_ATTR(DEVICE_, COMPUTE_CAPABILITY_MINOR_NV);
-    ADD_ATTR(DEVICE_, REGISTERS_PER_BLOCK_NV);
-    ADD_ATTR(DEVICE_, WARP_SIZE_NV);
-    ADD_ATTR(DEVICE_, GPU_OVERLAP_NV);
-    ADD_ATTR(DEVICE_, KERNEL_EXEC_TIMEOUT_NV);
-    ADD_ATTR(DEVICE_, INTEGRATED_MEMORY_NV);
-#endif
-// {{{ cl_amd_device_attribute_query
-#ifdef CL_DEVICE_PROFILING_TIMER_OFFSET_AMD
-    ADD_ATTR(DEVICE_, PROFILING_TIMER_OFFSET_AMD);
-#endif
-#ifdef CL_DEVICE_TOPOLOGY_AMD
-    ADD_ATTR(DEVICE_, TOPOLOGY_AMD);
-#endif
-#ifdef CL_DEVICE_BOARD_NAME_AMD
-    ADD_ATTR(DEVICE_, BOARD_NAME_AMD);
-#endif
-#ifdef CL_DEVICE_GLOBAL_FREE_MEMORY_AMD
-    ADD_ATTR(DEVICE_, GLOBAL_FREE_MEMORY_AMD);
-#endif
-#ifdef CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD
-    ADD_ATTR(DEVICE_, SIMD_PER_COMPUTE_UNIT_AMD);
-#endif
-#ifdef CL_DEVICE_SIMD_WIDTH_AMD
-    ADD_ATTR(DEVICE_, SIMD_WIDTH_AMD);
-#endif
-#ifdef CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD
-    ADD_ATTR(DEVICE_, SIMD_INSTRUCTION_WIDTH_AMD);
-#endif
-#ifdef CL_DEVICE_WAVEFRONT_WIDTH_AMD
-    ADD_ATTR(DEVICE_, WAVEFRONT_WIDTH_AMD);
-#endif
-#ifdef CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD
-    ADD_ATTR(DEVICE_, GLOBAL_MEM_CHANNELS_AMD);
-#endif
-#ifdef CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD
-    ADD_ATTR(DEVICE_, GLOBAL_MEM_CHANNEL_BANKS_AMD);
-#endif
-#ifdef CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD
-    ADD_ATTR(DEVICE_, GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD);
-#endif
-#ifdef CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD
-    ADD_ATTR(DEVICE_, LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD);
-#endif
-#ifdef CL_DEVICE_LOCAL_MEM_BANKS_AMD
-    ADD_ATTR(DEVICE_, LOCAL_MEM_BANKS_AMD);
-#endif
-// }}}
-#ifdef CL_DEVICE_MAX_ATOMIC_COUNTERS_EXT
-    ADD_ATTR(DEVICE_, MAX_ATOMIC_COUNTERS_EXT);
-#endif
-#if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION)
-    ADD_ATTR(DEVICE_, PARENT_DEVICE_EXT);
-    ADD_ATTR(DEVICE_, PARTITION_TYPES_EXT);
-    ADD_ATTR(DEVICE_, AFFINITY_DOMAINS_EXT);
-    ADD_ATTR(DEVICE_, REFERENCE_COUNT_EXT);
-    ADD_ATTR(DEVICE_, PARTITION_STYLE_EXT);
-#endif
-#if PYOPENCL_CL_VERSION >= 0x1020
-    ADD_ATTR(DEVICE_, LINKER_AVAILABLE);
-    ADD_ATTR(DEVICE_, BUILT_IN_KERNELS);
-    ADD_ATTR(DEVICE_, IMAGE_MAX_BUFFER_SIZE);
-    ADD_ATTR(DEVICE_, IMAGE_MAX_ARRAY_SIZE);
-    ADD_ATTR(DEVICE_, PARENT_DEVICE);
-    ADD_ATTR(DEVICE_, PARTITION_MAX_SUB_DEVICES);
-    ADD_ATTR(DEVICE_, PARTITION_PROPERTIES);
-    ADD_ATTR(DEVICE_, PARTITION_AFFINITY_DOMAIN);
-    ADD_ATTR(DEVICE_, PARTITION_TYPE);
-    ADD_ATTR(DEVICE_, REFERENCE_COUNT);
-    ADD_ATTR(DEVICE_, PREFERRED_INTEROP_USER_SYNC);
-    ADD_ATTR(DEVICE_, PRINTF_BUFFER_SIZE);
-#endif
-#ifdef cl_khr_image2d_from_buffer
-    ADD_ATTR(DEVICE_, IMAGE_PITCH_ALIGNMENT);
-    ADD_ATTR(DEVICE_, IMAGE_BASE_ADDRESS_ALIGNMENT);
-#endif
-  }
-
-  {
-    py::class_<device_fp_config> cls("device_fp_config", py::no_init);
-    ADD_ATTR(FP_, DENORM);
-    ADD_ATTR(FP_, INF_NAN);
-    ADD_ATTR(FP_, ROUND_TO_NEAREST);
-    ADD_ATTR(FP_, ROUND_TO_ZERO);
-    ADD_ATTR(FP_, ROUND_TO_INF);
-    ADD_ATTR(FP_, FMA);
-#if PYOPENCL_CL_VERSION >= 0x1010
-    ADD_ATTR(FP_, SOFT_FLOAT);
-#endif
-#if PYOPENCL_CL_VERSION >= 0x1020
-    ADD_ATTR(FP_, CORRECTLY_ROUNDED_DIVIDE_SQRT);
-#endif
-  }
-
-  {
-    py::class_<device_mem_cache_type> cls("device_mem_cache_type", py::no_init);
-    ADD_ATTR( , NONE);
-    ADD_ATTR( , READ_ONLY_CACHE);
-    ADD_ATTR( , READ_WRITE_CACHE);
-  }
-
-  {
-    py::class_<device_local_mem_type> cls("device_local_mem_type", py::no_init);
-    ADD_ATTR( , LOCAL);
-    ADD_ATTR( , GLOBAL);
-  }
-
-  {
-    py::class_<device_exec_capabilities> cls("device_exec_capabilities", py::no_init);
-    ADD_ATTR(EXEC_, KERNEL);
-    ADD_ATTR(EXEC_, NATIVE_KERNEL);
-#ifdef CL_EXEC_IMMEDIATE_EXECUTION_INTEL
-    ADD_ATTR(EXEC_, IMMEDIATE_EXECUTION_INTEL);
-#endif
-  }
-
-  {
-    py::class_<command_queue_properties> cls("command_queue_properties", py::no_init);
-    ADD_ATTR(QUEUE_, OUT_OF_ORDER_EXEC_MODE_ENABLE);
-    ADD_ATTR(QUEUE_, PROFILING_ENABLE);
-#ifdef CL_QUEUE_IMMEDIATE_EXECUTION_ENABLE_INTEL
-    ADD_ATTR(QUEUE_, IMMEDIATE_EXECUTION_ENABLE_INTEL);
-#endif
-  }
-
-  {
-    py::class_<context_info> cls("context_info", py::no_init);
-    ADD_ATTR(CONTEXT_, REFERENCE_COUNT);
-    ADD_ATTR(CONTEXT_, DEVICES);
-    ADD_ATTR(CONTEXT_, PROPERTIES);
-#if PYOPENCL_CL_VERSION >= 0x1010
-    ADD_ATTR(CONTEXT_, NUM_DEVICES);
-#endif
-#if PYOPENCL_CL_VERSION >= 0x1020
-    ADD_ATTR(CONTEXT_, INTEROP_USER_SYNC);
-#endif
-  }
-
-  {
-    py::class_<gl_context_info> cls("gl_context_info", py::no_init);
-#if defined(cl_khr_gl_sharing) && (cl_khr_gl_sharing >= 1)
-    ADD_ATTR(, CURRENT_DEVICE_FOR_GL_CONTEXT_KHR);
-    ADD_ATTR(, DEVICES_FOR_GL_CONTEXT_KHR);
-#endif
-  }
-
-  {
-    py::class_<context_properties> cls("context_properties", py::no_init);
-    ADD_ATTR(CONTEXT_, PLATFORM);
-#if defined(cl_khr_gl_sharing) && (cl_khr_gl_sharing >= 1)
-    ADD_ATTR( ,GL_CONTEXT_KHR);
-    ADD_ATTR( ,EGL_DISPLAY_KHR);
-    ADD_ATTR( ,GLX_DISPLAY_KHR);
-    ADD_ATTR( ,WGL_HDC_KHR);
-    ADD_ATTR( ,CGL_SHAREGROUP_KHR);
-#endif
-#if defined(__APPLE__) && defined(HAVE_GL)
-    ADD_ATTR( ,CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE);
-#endif /* __APPLE__ */
-// cl_amd_offline_devices
-#ifdef CL_CONTEXT_OFFLINE_DEVICES_AMD
-    ADD_ATTR(CONTEXT_, OFFLINE_DEVICES_AMD);
-#endif
-  }
-
-  {
-    py::class_<command_queue_info> cls("command_queue_info", py::no_init);
-    ADD_ATTR(QUEUE_, CONTEXT);
-    ADD_ATTR(QUEUE_, DEVICE);
-    ADD_ATTR(QUEUE_, REFERENCE_COUNT);
-    ADD_ATTR(QUEUE_, PROPERTIES);
-  }
-
-  {
-    py::class_<mem_flags> cls("mem_flags", py::no_init);
-    ADD_ATTR(MEM_, READ_WRITE);
-    ADD_ATTR(MEM_, WRITE_ONLY);
-    ADD_ATTR(MEM_, READ_ONLY);
-    ADD_ATTR(MEM_, USE_HOST_PTR);
-    ADD_ATTR(MEM_, ALLOC_HOST_PTR);
-    ADD_ATTR(MEM_, COPY_HOST_PTR);
-#ifdef cl_amd_device_memory_flags
-    ADD_ATTR(MEM_, USE_PERSISTENT_MEM_AMD);
-#endif
-#if PYOPENCL_CL_VERSION >= 0x1020
-    ADD_ATTR(MEM_, HOST_WRITE_ONLY);
-    ADD_ATTR(MEM_, HOST_READ_ONLY);
-    ADD_ATTR(MEM_, HOST_NO_ACCESS);
-#endif
-  }
-
-  {
-    py::class_<channel_order> cls("channel_order", py::no_init);
-    ADD_ATTR( , R);
-    ADD_ATTR( , A);
-    ADD_ATTR( , RG);
-    ADD_ATTR( , RA);
-    ADD_ATTR( , RGB);
-    ADD_ATTR( , RGBA);
-    ADD_ATTR( , BGRA);
-    ADD_ATTR( , INTENSITY);
-    ADD_ATTR( , LUMINANCE);
-#if PYOPENCL_CL_VERSION >= 0x1010
-    ADD_ATTR( , Rx);
-    ADD_ATTR( , RGx);
-    ADD_ATTR( , RGBx);
-#endif
-  }
-
-  {
-    py::class_<channel_type> cls("channel_type", py::no_init);
-    ADD_ATTR( , SNORM_INT8);
-    ADD_ATTR( , SNORM_INT16);
-    ADD_ATTR( , UNORM_INT8);
-    ADD_ATTR( , UNORM_INT16);
-    ADD_ATTR( , UNORM_SHORT_565);
-    ADD_ATTR( , UNORM_SHORT_555);
-    ADD_ATTR( , UNORM_INT_101010);
-    ADD_ATTR( , SIGNED_INT8);
-    ADD_ATTR( , SIGNED_INT16);
-    ADD_ATTR( , SIGNED_INT32);
-    ADD_ATTR( , UNSIGNED_INT8);
-    ADD_ATTR( , UNSIGNED_INT16);
-    ADD_ATTR( , UNSIGNED_INT32);
-    ADD_ATTR( , HALF_FLOAT);
-    ADD_ATTR( , FLOAT);
-  }
-
-  {
-    py::class_<mem_object_type> cls("mem_object_type", py::no_init);
-    ADD_ATTR(MEM_OBJECT_, BUFFER);
-    ADD_ATTR(MEM_OBJECT_, IMAGE2D);
-    ADD_ATTR(MEM_OBJECT_, IMAGE3D);
-#if PYOPENCL_CL_VERSION >= 0x1020
-    ADD_ATTR(MEM_OBJECT_, IMAGE2D_ARRAY);
-    ADD_ATTR(MEM_OBJECT_, IMAGE1D);
-    ADD_ATTR(MEM_OBJECT_, IMAGE1D_ARRAY);
-    ADD_ATTR(MEM_OBJECT_, IMAGE1D_BUFFER);
-#endif
-  }
-
-  {
-    py::class_<mem_info> cls("mem_info", py::no_init);
-    ADD_ATTR(MEM_, TYPE);
-    ADD_ATTR(MEM_, FLAGS);
-    ADD_ATTR(MEM_, SIZE);
-    ADD_ATTR(MEM_, HOST_PTR);
-    ADD_ATTR(MEM_, MAP_COUNT);
-    ADD_ATTR(MEM_, REFERENCE_COUNT);
-    ADD_ATTR(MEM_, CONTEXT);
-#if PYOPENCL_CL_VERSION >= 0x1010
-    ADD_ATTR(MEM_, ASSOCIATED_MEMOBJECT);
-    ADD_ATTR(MEM_, OFFSET);
-#endif
-  }
-
-  {
-    py::class_<image_info> cls("image_info", py::no_init);
-    ADD_ATTR(IMAGE_, FORMAT);
-    ADD_ATTR(IMAGE_, ELEMENT_SIZE);
-    ADD_ATTR(IMAGE_, ROW_PITCH);
-    ADD_ATTR(IMAGE_, SLICE_PITCH);
-    ADD_ATTR(IMAGE_, WIDTH);
-    ADD_ATTR(IMAGE_, HEIGHT);
-    ADD_ATTR(IMAGE_, DEPTH);
-#if PYOPENCL_CL_VERSION >= 0x1020
-    ADD_ATTR(IMAGE_, ARRAY_SIZE);
-    ADD_ATTR(IMAGE_, BUFFER);
-    ADD_ATTR(IMAGE_, NUM_MIP_LEVELS);
-    ADD_ATTR(IMAGE_, NUM_SAMPLES);
-#endif
-  }
-
-  {
-    py::class_<addressing_mode> cls("addressing_mode", py::no_init);
-    ADD_ATTR(ADDRESS_, NONE);
-    ADD_ATTR(ADDRESS_, CLAMP_TO_EDGE);
-    ADD_ATTR(ADDRESS_, CLAMP);
-    ADD_ATTR(ADDRESS_, REPEAT);
-#if PYOPENCL_CL_VERSION >= 0x1010
-    ADD_ATTR(ADDRESS_, MIRRORED_REPEAT);
-#endif
-  }
-
-  {
-    py::class_<filter_mode> cls("filter_mode", py::no_init);
-    ADD_ATTR(FILTER_, NEAREST);
-    ADD_ATTR(FILTER_, LINEAR);
-  }
-
-  {
-    py::class_<sampler_info> cls("sampler_info", py::no_init);
-    ADD_ATTR(SAMPLER_, REFERENCE_COUNT);
-    ADD_ATTR(SAMPLER_, CONTEXT);
-    ADD_ATTR(SAMPLER_, NORMALIZED_COORDS);
-    ADD_ATTR(SAMPLER_, ADDRESSING_MODE);
-    ADD_ATTR(SAMPLER_, FILTER_MODE);
-  }
-
-  {
-    py::class_<map_flags> cls("map_flags", py::no_init);
-    ADD_ATTR(MAP_, READ);
-    ADD_ATTR(MAP_, WRITE);
-#if PYOPENCL_CL_VERSION >= 0x1020
-    ADD_ATTR(MAP_, WRITE_INVALIDATE_REGION);
-#endif
-  }
-
-  {
-    py::class_<program_info> cls("program_info", py::no_init);
-    ADD_ATTR(PROGRAM_, REFERENCE_COUNT);
-    ADD_ATTR(PROGRAM_, CONTEXT);
-    ADD_ATTR(PROGRAM_, NUM_DEVICES);
-    ADD_ATTR(PROGRAM_, DEVICES);
-    ADD_ATTR(PROGRAM_, SOURCE);
-    ADD_ATTR(PROGRAM_, BINARY_SIZES);
-    ADD_ATTR(PROGRAM_, BINARIES);
-#if PYOPENCL_CL_VERSION >= 0x1020
-    ADD_ATTR(PROGRAM_, NUM_KERNELS);
-    ADD_ATTR(PROGRAM_, KERNEL_NAMES);
-#endif
-  }
-
-  {
-    py::class_<program_build_info> cls("program_build_info", py::no_init);
-    ADD_ATTR(PROGRAM_BUILD_, STATUS);
-    ADD_ATTR(PROGRAM_BUILD_, OPTIONS);
-    ADD_ATTR(PROGRAM_BUILD_, LOG);
-#if PYOPENCL_CL_VERSION >= 0x1020
-    ADD_ATTR(PROGRAM_, BINARY_TYPE);
-#endif
-  }
-
-  {
-    py::class_<program_binary_type> cls("program_binary_type", py::no_init);
-#if PYOPENCL_CL_VERSION >= 0x1020
-    ADD_ATTR(PROGRAM_BINARY_TYPE_, NONE);
-    ADD_ATTR(PROGRAM_BINARY_TYPE_, COMPILED_OBJECT);
-    ADD_ATTR(PROGRAM_BINARY_TYPE_, LIBRARY);
-    ADD_ATTR(PROGRAM_BINARY_TYPE_, EXECUTABLE);
-#endif
-  }
-
-  {
-    py::class_<kernel_info> cls("kernel_info", py::no_init);
-    ADD_ATTR(KERNEL_, FUNCTION_NAME);
-    ADD_ATTR(KERNEL_, NUM_ARGS);
-    ADD_ATTR(KERNEL_, REFERENCE_COUNT);
-    ADD_ATTR(KERNEL_, CONTEXT);
-    ADD_ATTR(KERNEL_, PROGRAM);
-#if PYOPENCL_CL_VERSION >= 0x1020
-    ADD_ATTR(KERNEL_, ATTRIBUTES);
-#endif
-  }
-
-  {
-    py::class_<kernel_arg_info> cls("kernel_arg_info", py::no_init);
-#if PYOPENCL_CL_VERSION >= 0x1020
-    ADD_ATTR(KERNEL_ARG_, ADDRESS_QUALIFIER);
-    ADD_ATTR(KERNEL_ARG_, ACCESS_QUALIFIER);
-    ADD_ATTR(KERNEL_ARG_, TYPE_NAME);
-    ADD_ATTR(KERNEL_ARG_, NAME);
-#endif
-  }
-
-  {
-    py::class_<kernel_arg_address_qualifier> cls(
-        "kernel_arg_address_qualifier", py::no_init);
-#if PYOPENCL_CL_VERSION >= 0x1020
-    ADD_ATTR(KERNEL_ARG_ADDRESS_, GLOBAL);
-    ADD_ATTR(KERNEL_ARG_ADDRESS_, LOCAL);
-    ADD_ATTR(KERNEL_ARG_ADDRESS_, CONSTANT);
-    ADD_ATTR(KERNEL_ARG_ADDRESS_, PRIVATE);
-#endif
-  }
-
-  {
-    py::class_<kernel_arg_access_qualifier> cls(
-        "kernel_arg_access_qualifier", py::no_init);
-#if PYOPENCL_CL_VERSION >= 0x1020
-    ADD_ATTR(KERNEL_ARG_ACCESS_, READ_ONLY);
-    ADD_ATTR(KERNEL_ARG_ACCESS_, WRITE_ONLY);
-    ADD_ATTR(KERNEL_ARG_ACCESS_, READ_WRITE);
-    ADD_ATTR(KERNEL_ARG_ACCESS_, NONE);
-#endif
-  }
-
-  {
-    py::class_<kernel_work_group_info> cls("kernel_work_group_info", py::no_init);
-    ADD_ATTR(KERNEL_, WORK_GROUP_SIZE);
-    ADD_ATTR(KERNEL_, COMPILE_WORK_GROUP_SIZE);
-    ADD_ATTR(KERNEL_, LOCAL_MEM_SIZE);
-#if PYOPENCL_CL_VERSION >= 0x1010
-    ADD_ATTR(KERNEL_, PREFERRED_WORK_GROUP_SIZE_MULTIPLE);
-    ADD_ATTR(KERNEL_, PRIVATE_MEM_SIZE);
-#endif
-#if PYOPENCL_CL_VERSION >= 0x1020
-    ADD_ATTR(KERNEL_, GLOBAL_WORK_SIZE);
-#endif
-  }
-
-  {
-    py::class_<event_info> cls("event_info", py::no_init);
-    ADD_ATTR(EVENT_, COMMAND_QUEUE);
-    ADD_ATTR(EVENT_, COMMAND_TYPE);
-    ADD_ATTR(EVENT_, REFERENCE_COUNT);
-    ADD_ATTR(EVENT_, COMMAND_EXECUTION_STATUS);
-#if PYOPENCL_CL_VERSION >= 0x1010
-    ADD_ATTR(EVENT_, CONTEXT);
-#endif
-  }
-
-  {
-    py::class_<command_type> cls("command_type", py::no_init);
-    ADD_ATTR(COMMAND_, NDRANGE_KERNEL);
-    ADD_ATTR(COMMAND_, TASK);
-    ADD_ATTR(COMMAND_, NATIVE_KERNEL);
-    ADD_ATTR(COMMAND_, READ_BUFFER);
-    ADD_ATTR(COMMAND_, WRITE_BUFFER);
-    ADD_ATTR(COMMAND_, COPY_BUFFER);
-    ADD_ATTR(COMMAND_, READ_IMAGE);
-    ADD_ATTR(COMMAND_, WRITE_IMAGE);
-    ADD_ATTR(COMMAND_, COPY_IMAGE);
-    ADD_ATTR(COMMAND_, COPY_IMAGE_TO_BUFFER);
-    ADD_ATTR(COMMAND_, COPY_BUFFER_TO_IMAGE);
-    ADD_ATTR(COMMAND_, MAP_BUFFER);
-    ADD_ATTR(COMMAND_, MAP_IMAGE);
-    ADD_ATTR(COMMAND_, UNMAP_MEM_OBJECT);
-    ADD_ATTR(COMMAND_, MARKER);
-    ADD_ATTR(COMMAND_, ACQUIRE_GL_OBJECTS);
-    ADD_ATTR(COMMAND_, RELEASE_GL_OBJECTS);
-#if PYOPENCL_CL_VERSION >= 0x1010
-    ADD_ATTR(COMMAND_, READ_BUFFER_RECT);
-    ADD_ATTR(COMMAND_, WRITE_BUFFER_RECT);
-    ADD_ATTR(COMMAND_, COPY_BUFFER_RECT);
-    ADD_ATTR(COMMAND_, USER);
-#endif
-#ifdef cl_ext_migrate_memobject
-    ADD_ATTR(COMMAND_, MIGRATE_MEM_OBJECT_EXT);
-#endif
-#if PYOPENCL_CL_VERSION >= 0x1020
-    ADD_ATTR(COMMAND_, BARRIER);
-    ADD_ATTR(COMMAND_, MIGRATE_MEM_OBJECTS);
-    ADD_ATTR(COMMAND_, FILL_BUFFER);
-    ADD_ATTR(COMMAND_, FILL_IMAGE);
-#endif
-  }
-
-  {
-    py::class_<command_execution_status> cls("command_execution_status", py::no_init);
-    ADD_ATTR(, COMPLETE);
-    ADD_ATTR(, RUNNING);
-    ADD_ATTR(, SUBMITTED);
-    ADD_ATTR(, QUEUED);
-  }
-
-  {
-    py::class_<profiling_info> cls("profiling_info", py::no_init);
-    ADD_ATTR(PROFILING_COMMAND_, QUEUED);
-    ADD_ATTR(PROFILING_COMMAND_, SUBMIT);
-    ADD_ATTR(PROFILING_COMMAND_, START);
-    ADD_ATTR(PROFILING_COMMAND_, END);
-  }
-
-/* not needed--filled in automatically by implementation.
-#if PYOPENCL_CL_VERSION >= 0x1010
-  {
-    py::class_<buffer_create_type> cls("buffer_create_type", py::no_init);
-    ADD_ATTR(BUFFER_CREATE_TYPE_, REGION);
-  }
-#endif
-*/
-
-  {
-    py::class_<mem_migration_flags> cls(
-        "mem_migration_flags", py::no_init);
-#if PYOPENCL_CL_VERSION >= 0x1020
-    ADD_ATTR(MIGRATE_MEM_OBJECT_, HOST);
-    ADD_ATTR(MIGRATE_MEM_OBJECT_, CONTENT_UNDEFINED);
-#endif
-  }
-
-  {
-    py::class_<device_partition_property_ext> cls(
-        "device_partition_property_ext", py::no_init);
-#if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION)
-    ADD_ATTR_SUFFIX(DEVICE_PARTITION_, EQUALLY, _EXT);
-    ADD_ATTR_SUFFIX(DEVICE_PARTITION_, BY_COUNTS, _EXT);
-    ADD_ATTR_SUFFIX(DEVICE_PARTITION_, BY_NAMES, _EXT);
-    ADD_ATTR_SUFFIX(DEVICE_PARTITION_, BY_AFFINITY_DOMAIN, _EXT);
-    ADD_ATTR_SUFFIX(, PROPERTIES_LIST_END, _EXT);
-    ADD_ATTR_SUFFIX(, PARTITION_BY_COUNTS_LIST_END, _EXT);
-    ADD_ATTR_SUFFIX(, PARTITION_BY_NAMES_LIST_END, _EXT);
-#endif
-  }
-
-  {
-    py::class_<affinity_domain_ext> cls("affinity_domain_ext", py::no_init);
-#if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION)
-    ADD_ATTR_SUFFIX(AFFINITY_DOMAIN_, L1_CACHE, _EXT);
-    ADD_ATTR_SUFFIX(AFFINITY_DOMAIN_, L2_CACHE, _EXT);
-    ADD_ATTR_SUFFIX(AFFINITY_DOMAIN_, L3_CACHE, _EXT);
-    ADD_ATTR_SUFFIX(AFFINITY_DOMAIN_, L4_CACHE, _EXT);
-    ADD_ATTR_SUFFIX(AFFINITY_DOMAIN_, NUMA, _EXT);
-    ADD_ATTR_SUFFIX(AFFINITY_DOMAIN_, NEXT_FISSIONABLE, _EXT);
-#endif
-  }
-
-  {
-    py::class_<device_partition_property> cls(
-        "device_partition_property", py::no_init);
-#if PYOPENCL_CL_VERSION >= 0x1020
-    ADD_ATTR(DEVICE_PARTITION_, EQUALLY);
-    ADD_ATTR(DEVICE_PARTITION_, BY_COUNTS);
-    ADD_ATTR(DEVICE_PARTITION_, BY_COUNTS_LIST_END);
-    ADD_ATTR(DEVICE_PARTITION_, BY_AFFINITY_DOMAIN);
-#endif
-  }
-
-  {
-    py::class_<device_affinity_domain> cls("device_affinity_domain", py::no_init);
-#if PYOPENCL_CL_VERSION >= 0x1020
-    ADD_ATTR(DEVICE_AFFINITY_DOMAIN_, NUMA);
-    ADD_ATTR(DEVICE_AFFINITY_DOMAIN_, L4_CACHE);
-    ADD_ATTR(DEVICE_AFFINITY_DOMAIN_, L3_CACHE);
-    ADD_ATTR(DEVICE_AFFINITY_DOMAIN_, L2_CACHE);
-    ADD_ATTR(DEVICE_AFFINITY_DOMAIN_, L1_CACHE);
-    ADD_ATTR(DEVICE_AFFINITY_DOMAIN_, NEXT_PARTITIONABLE);
-#endif
-  }
-
-#ifdef HAVE_GL
-  {
-    py::class_<gl_object_type> cls("gl_object_type", py::no_init);
-    ADD_ATTR(GL_OBJECT_, BUFFER);
-    ADD_ATTR(GL_OBJECT_, TEXTURE2D);
-    ADD_ATTR(GL_OBJECT_, TEXTURE3D);
-    ADD_ATTR(GL_OBJECT_, RENDERBUFFER);
-  }
-
-  {
-    py::class_<gl_texture_info> cls("gl_texture_info", py::no_init);
-    ADD_ATTR(GL_, TEXTURE_TARGET);
-    ADD_ATTR(GL_, MIPMAP_LEVEL);
-  }
-#endif
-
-  {
-    py::class_<migrate_mem_object_flags_ext> cls("migrate_mem_object_flags_ext", py::no_init);
-#ifdef cl_ext_migrate_memobject
-    ADD_ATTR_SUFFIX(MIGRATE_MEM_OBJECT_, HOST, _EXT);
-#endif
-  }
-
-  // }}}
-}
-
-
-
-
-// vim: foldmethod=marker
diff --git a/src/wrapper/wrap_helpers.hpp b/src/wrapper/wrap_helpers.hpp
deleted file mode 100644
index dac179c7..00000000
--- a/src/wrapper/wrap_helpers.hpp
+++ /dev/null
@@ -1,175 +0,0 @@
-#ifndef PYCUDA_WRAP_HELPERS_HEADER_SEEN
-#define PYCUDA_WRAP_HELPERS_HEADER_SEEN
-
-
-
-
-#include <boost/version.hpp>
-#include <boost/python.hpp>
-#include <boost/python/stl_iterator.hpp>
-
-
-
-
-namespace py = boost::python;
-
-
-
-
-#if (BOOST_VERSION/100) < 1035
-#warning *******************************************************************
-#warning **** Your version of Boost C++ is likely too old for PyOpenCL. ****
-#warning *******************************************************************
-#endif
-
-
-
-
-#define PYTHON_ERROR(TYPE, REASON) \
-{ \
-  PyErr_SetString(PyExc_##TYPE, REASON); \
-  throw boost::python::error_already_set(); \
-}
-
-#define ENUM_VALUE(NAME) \
-  value(#NAME, NAME)
-
-#define DEF_SIMPLE_METHOD(NAME) \
-  def(#NAME, &cls::NAME)
-
-#define DEF_SIMPLE_METHOD_WITH_ARGS(NAME, ARGS) \
-  def(#NAME, &cls::NAME, boost::python::args ARGS)
-
-#define DEF_SIMPLE_FUNCTION(NAME) \
-  boost::python::def(#NAME, &NAME)
-
-#define DEF_SIMPLE_FUNCTION_WITH_ARGS(NAME, ARGS) \
-  boost::python::def(#NAME, &NAME, boost::python::args ARGS)
-
-#define DEF_SIMPLE_RO_MEMBER(NAME) \
-  def_readonly(#NAME, &cls::m_##NAME)
-
-#define DEF_SIMPLE_RW_MEMBER(NAME) \
-  def_readwrite(#NAME, &cls::m_##NAME)
-
-#define PYTHON_FOREACH(NAME, ITERABLE) \
-  BOOST_FOREACH(boost::python::object NAME, \
-      std::make_pair( \
-        boost::python::stl_input_iterator<boost::python::object>(ITERABLE), \
-        boost::python::stl_input_iterator<boost::python::object>()))
-
-#define COPY_PY_LIST(TYPE, NAME) \
-  std::copy( \
-      boost::python::stl_input_iterator<TYPE>(py_##NAME), \
-      boost::python::stl_input_iterator<TYPE>(), \
-      std::back_inserter(NAME));
-
-#define COPY_PY_COORD_TRIPLE(NAME) \
-  size_t NAME[3] = {0, 0, 0}; \
-  { \
-    size_t my_len = len(py_##NAME); \
-    if (my_len > 3) \
-      throw error("transfer", CL_INVALID_VALUE, #NAME "has too many components"); \
-    for (size_t i = 0; i < my_len; ++i) \
-      NAME[i] = py::extract<size_t>(py_##NAME[i])(); \
-  }
-
-#define COPY_PY_PITCH_TUPLE(NAME) \
-  size_t NAME[2] = {0, 0}; \
-  if (py_##NAME.ptr() != Py_None) \
-  { \
-    size_t my_len = len(py_##NAME); \
-    if (my_len > 2) \
-      throw error("transfer", CL_INVALID_VALUE, #NAME "has too many components"); \
-    for (size_t i = 0; i < my_len; ++i) \
-      NAME[i] = py::extract<size_t>(py_##NAME[i])(); \
-  }
-
-#define COPY_PY_REGION_TRIPLE(NAME) \
-  size_t NAME[3] = {1, 1, 1}; \
-  { \
-    size_t my_len = len(py_##NAME); \
-    if (my_len > 3) \
-      throw error("transfer", CL_INVALID_VALUE, #NAME "has too many components"); \
-    for (size_t i = 0; i < my_len; ++i) \
-      NAME[i] = py::extract<size_t>(py_##NAME[i])(); \
-  }
-
-#define PYOPENCL_PARSE_NUMPY_ARRAY_SPEC \
-    PyArray_Descr *tp_descr; \
-    if (PyArray_DescrConverter(dtype.ptr(), &tp_descr) != NPY_SUCCEED) \
-      throw py::error_already_set(); \
-    \
-    py::extract<npy_intp> shape_as_int(py_shape); \
-    std::vector<npy_intp> shape; \
-    \
-    if (shape_as_int.check()) \
-      shape.push_back(shape_as_int()); \
-    else \
-      COPY_PY_LIST(npy_intp, shape); \
-    \
-    NPY_ORDER order = PyArray_CORDER; \
-    PyArray_OrderConverter(py_order.ptr(), &order); \
-    \
-    int ary_flags = 0; \
-    if (order == PyArray_FORTRANORDER) \
-      ary_flags |= NPY_FARRAY; \
-    else if (order == PyArray_CORDER) \
-      ary_flags |= NPY_CARRAY; \
-    else \
-      throw std::runtime_error("unrecognized order specifier"); \
-    \
-    std::vector<npy_intp> strides; \
-    if (py_strides.ptr() != Py_None) \
-    { \
-      COPY_PY_LIST(npy_intp, strides); \
-    }
-
-#define PYOPENCL_RETURN_VECTOR(ITEMTYPE, NAME) \
-  { \
-    py::list pyopencl_result; \
-    BOOST_FOREACH(ITEMTYPE item, NAME) \
-      pyopencl_result.append(item); \
-    return pyopencl_result; \
-  }
-
-namespace
-{
-  template <typename T>
-  inline boost::python::handle<> handle_from_new_ptr(T *ptr)
-  {
-    return boost::python::handle<>(
-        typename boost::python::manage_new_object::apply<T *>::type()(ptr));
-  }
-
-  template <typename T, typename ClType>
-  inline T *from_int_ptr(intptr_t obj_ref)
-  {
-    ClType clobj = (ClType) obj_ref;
-    return new T(clobj, /* retain */ true);
-  }
-
-  template <typename T>
-  inline intptr_t to_int_ptr(T const &obj)
-  {
-    return (intptr_t) obj.data();
-  }
-}
-
-#define PYOPENCL_EXPOSE_TO_FROM_INT_PTR(CL_TYPENAME) \
-  .def("from_int_ptr", from_int_ptr<cls, CL_TYPENAME>, \
-      py::return_value_policy<py::manage_new_object>(), \
-      py::arg("int_ptr_value"), \
-      "(static method) Return a new Python object referencing the C-level " \
-      ":c:type:`" #CL_TYPENAME "` object at the location pointed to " \
-      "by *int_ptr_value*. The relevant :c:func:`clRetain*` function " \
-      "will be called." \
-      "\n\n.. versionadded:: 2013.2\n") \
-  .staticmethod("from_int_ptr") \
-  .add_property("int_ptr", to_int_ptr<cls>, \
-      "Return an integer corresponding to the pointer value " \
-      "of the underlying :c:type:`" #CL_TYPENAME "`. " \
-      "Use :meth:`from_int_ptr` to turn back into a Python object." \
-      "\n\n.. versionadded:: 2013.2\n") \
-
-#endif
diff --git a/src/wrapper/wrap_mempool.cpp b/src/wrapper/wrap_mempool.cpp
deleted file mode 100644
index 73df3bd1..00000000
--- a/src/wrapper/wrap_mempool.cpp
+++ /dev/null
@@ -1,290 +0,0 @@
-// Gregor Thalhammer (on Apr 13, 2011) said it's necessary to import Python.h 
-// first to prevent OS X from overriding a bunch of macros. (e.g. isspace)
-#include <Python.h>
-
-#include <vector>
-#include "wrap_helpers.hpp"
-#include "wrap_cl.hpp"
-#include "mempool.hpp"
-#include "tools.hpp"
-#include <boost/python/stl_iterator.hpp>
-
-
-
-
-namespace py = boost::python;
-
-
-
-
-namespace
-{
-  class cl_allocator_base
-  {
-    protected:
-      boost::shared_ptr<pyopencl::context> m_context;
-      cl_mem_flags m_flags;
-
-    public:
-      cl_allocator_base(boost::shared_ptr<pyopencl::context> const &ctx,
-          cl_mem_flags flags=CL_MEM_READ_WRITE)
-        : m_context(ctx), m_flags(flags)
-      {
-        if (flags & (CL_MEM_USE_HOST_PTR | CL_MEM_COPY_HOST_PTR))
-          throw pyopencl::error("Allocator", CL_INVALID_VALUE,
-              "cannot specify USE_HOST_PTR or COPY_HOST_PTR flags");
-      }
-
-      cl_allocator_base(cl_allocator_base const &src)
-      : m_context(src.m_context), m_flags(src.m_flags)
-      { }
-
-      virtual ~cl_allocator_base()
-      { }
-
-      typedef cl_mem pointer_type;
-      typedef size_t size_type;
-
-      virtual cl_allocator_base *copy() const = 0;
-      virtual bool is_deferred() const = 0;
-      virtual pointer_type allocate(size_type s) = 0;
-
-      void free(pointer_type p)
-      {
-        PYOPENCL_CALL_GUARDED(clReleaseMemObject, (p));
-      }
-
-      void try_release_blocks()
-      {
-        pyopencl::run_python_gc();
-      }
-  };
-
-  class cl_deferred_allocator : public cl_allocator_base
-  {
-    private:
-      typedef cl_allocator_base super;
-
-    public:
-      cl_deferred_allocator(boost::shared_ptr<pyopencl::context> const &ctx,
-          cl_mem_flags flags=CL_MEM_READ_WRITE)
-        : super(ctx, flags)
-      { }
-
-      cl_allocator_base *copy() const
-      {
-        return new cl_deferred_allocator(*this);
-      }
-
-      bool is_deferred() const
-      { return true; }
-
-      pointer_type allocate(size_type s)
-      {
-        return pyopencl::create_buffer(m_context->data(), m_flags, s, 0);
-      }
-  };
-
-  const unsigned zero = 0;
-
-  class cl_immediate_allocator : public cl_allocator_base
-  {
-    private:
-      typedef cl_allocator_base super;
-      pyopencl::command_queue m_queue;
-
-    public:
-      cl_immediate_allocator(pyopencl::command_queue &queue,
-          cl_mem_flags flags=CL_MEM_READ_WRITE)
-        : super(boost::shared_ptr<pyopencl::context>(queue.get_context()), flags),
-        m_queue(queue.data(), /*retain*/ true)
-      { }
-
-      cl_immediate_allocator(cl_immediate_allocator const &src)
-        : super(src), m_queue(src.m_queue)
-      { }
-
-      cl_allocator_base *copy() const
-      {
-        return new cl_immediate_allocator(*this);
-      }
-
-      bool is_deferred() const
-      { return false; }
-
-      pointer_type allocate(size_type s)
-      {
-        pointer_type ptr =  pyopencl::create_buffer(
-            m_context->data(), m_flags, s, 0);
-
-        // Make sure the buffer gets allocated right here and right now.
-        // This looks (and is) expensive. But immediate allocators
-        // have their main use in memory pools, whose basic assumption
-        // is that allocation is too expensive anyway--but they rely
-        // on exact 'out-of-memory' information.
-        unsigned zero = 0;
-        PYOPENCL_CALL_GUARDED(clEnqueueWriteBuffer, (
-              m_queue.data(),
-              ptr,
-              /* is blocking */ CL_FALSE,
-              0, std::min(s, sizeof(zero)), &zero,
-              0, NULL, NULL
-              ));
-
-        // No need to wait for completion here. clWaitForEvents (e.g.)
-        // cannot return mem object allocation failures. This implies that
-        // the buffer is faulted onto the device on enqueue.
-
-        return ptr;
-      }
-  };
-
-
-
-
-  inline
-  pyopencl::buffer *allocator_call(cl_allocator_base &alloc, size_t size)
-  {
-    cl_mem mem;
-    int try_count = 0;
-    while (try_count < 2)
-    {
-      try
-      {
-        mem = alloc.allocate(size);
-        break;
-      }
-      catch (pyopencl::error &e)
-      {
-        if (!e.is_out_of_memory())
-          throw;
-        if (++try_count == 2)
-          throw;
-      }
-
-      alloc.try_release_blocks();
-    }
-
-    try
-    {
-      return new pyopencl::buffer(mem, false);
-    }
-    catch (...)
-    {
-      PYOPENCL_CALL_GUARDED(clReleaseMemObject, (mem));
-      throw;
-    }
-  }
-
-
-
-
-  class pooled_buffer
-    : public pyopencl::pooled_allocation<pyopencl::memory_pool<cl_allocator_base> >,
-    public pyopencl::memory_object_holder
-  {
-    private:
-      typedef
-        pyopencl::pooled_allocation<pyopencl::memory_pool<cl_allocator_base> >
-        super;
-
-    public:
-      pooled_buffer(
-          boost::shared_ptr<super::pool_type> p, super::size_type s)
-        : super(p, s)
-      { }
-
-      const super::pointer_type data() const
-      { return ptr(); }
-  };
-
-
-
-
-  pooled_buffer *device_pool_allocate(
-      boost::shared_ptr<pyopencl::memory_pool<cl_allocator_base> > pool,
-      pyopencl::memory_pool<cl_allocator_base>::size_type sz)
-  {
-    return new pooled_buffer(pool, sz);
-  }
-
-
-
-
-  template<class Wrapper>
-  void expose_memory_pool(Wrapper &wrapper)
-  {
-    typedef typename Wrapper::wrapped_type cls;
-    wrapper
-      .add_property("held_blocks", &cls::held_blocks)
-      .add_property("active_blocks", &cls::active_blocks)
-      .DEF_SIMPLE_METHOD(bin_number)
-      .DEF_SIMPLE_METHOD(alloc_size)
-      .DEF_SIMPLE_METHOD(free_held)
-      .DEF_SIMPLE_METHOD(stop_holding)
-      .staticmethod("bin_number")
-      .staticmethod("alloc_size")
-      ;
-  }
-}
-
-
-
-
-void pyopencl_expose_mempool()
-{
-  py::def("bitlog2", pyopencl::bitlog2);
-
-  {
-    typedef cl_allocator_base cls;
-    py::class_<cls, boost::noncopyable> wrapper("_tools_AllocatorBase", py::no_init);
-    wrapper
-      .def("__call__", allocator_call,
-          py::return_value_policy<py::manage_new_object>())
-      ;
-
-  }
-
-  {
-    typedef cl_deferred_allocator cls;
-    py::class_<cls, py::bases<cl_allocator_base> > wrapper("_tools_DeferredAllocator",
-        py::init<
-          boost::shared_ptr<pyopencl::context> const &,
-          py::optional<cl_mem_flags> >());
-  }
-
-  {
-    typedef cl_immediate_allocator cls;
-    py::class_<cls, py::bases<cl_allocator_base> > wrapper("_tools_ImmediateAllocator",
-        py::init<pyopencl::command_queue &, py::optional<cl_mem_flags> >());
-  }
-
-  {
-    typedef pyopencl::memory_pool<cl_allocator_base> cls;
-
-    py::class_<
-      cls, boost::noncopyable,
-      boost::shared_ptr<cls> > wrapper("MemoryPool",
-          py::init<cl_allocator_base const &>()
-          );
-    wrapper
-      .def("allocate", device_pool_allocate,
-          py::return_value_policy<py::manage_new_object>())
-      .def("__call__", device_pool_allocate,
-          py::return_value_policy<py::manage_new_object>())
-      // undoc for now
-      .DEF_SIMPLE_METHOD(set_trace)
-      ;
-
-    expose_memory_pool(wrapper);
-  }
-
-  {
-    typedef pooled_buffer cls;
-    py::class_<cls, boost::noncopyable, 
-      py::bases<pyopencl::memory_object_holder> >(
-        "PooledBuffer", py::no_init)
-      .def("release", &cls::free)
-      ;
-  }
-}
-- 
GitLab