diff --git a/pyopencl/__init__.py b/pyopencl/__init__.py
index 19e9f62b593dfd9cbe81f87e7713d6269d1f7753..dccf5b415fb889c4ebf9c1d60ac2cc98f461394f 100644
--- a/pyopencl/__init__.py
+++ b/pyopencl/__init__.py
@@ -178,11 +178,6 @@ class Program(object):
         try:
             return build_func()
         except _cl.RuntimeError, e:
-            from pytools import Record
-
-            class ErrorRecord(Record):
-                pass
-
             what = e.what
             if options:
                 what = what + "\n(options: %s)" % " ".join(options)
@@ -200,11 +195,7 @@ class Program(object):
             code = e.code
             routine = e.routine
 
-            err = _cl.RuntimeError(
-                    ErrorRecord(
-                        what=lambda: what,
-                        code=lambda: code,
-                        routine=lambda: routine))
+            err = _cl.RuntimeError(routine, code, what)
 
         # Python 3.2 outputs the whole list of currently active exceptions
         # This serves to remove one (redundant) level from that nesting.
@@ -381,22 +372,13 @@ def _add_functionality():
         try:
             self._build(options=options, devices=devices)
         except Exception, e:
-            from pytools import Record
-
-            class ErrorRecord(Record):
-                pass
-
             what = e.what + "\n\n" + (75*"="+"\n").join(
                     "Build on %s:\n\n%s" % (dev, log)
                     for dev, log in self._get_build_logs())
             code = e.code
             routine = e.routine
 
-            err = _cl.RuntimeError(
-                    ErrorRecord(
-                        what=lambda: what,
-                        code=lambda: code,
-                        routine=lambda: routine))
+            err = _cl.RuntimeError(routine, code, what)
 
         if err is not None:
             # Python 3.2 outputs the whole list of currently active exceptions
diff --git a/pyopencl/cffi_cl.py b/pyopencl/cffi_cl.py
index d649de4a3c06026655a4658204ba799a8c68730a..198ad18e843b636921c20ac38a2a03e9b32cd930 100644
--- a/pyopencl/cffi_cl.py
+++ b/pyopencl/cffi_cl.py
@@ -1,5 +1,3 @@
-#from pyopencl._cl import RuntimeError
-
 import warnings
 
 import os.path
@@ -114,24 +112,20 @@ class _CArrays(_CArray):
         _lib._free2(_ffi.cast('void**', self.ptr[0]), self.size[0])
         super(_CArrays, self).__del__()
 
-class CLRuntimeError(RuntimeError):
-    def __init__(self, routine, code, msg=""):
-        super(CLRuntimeError, self).__init__(msg)
-        self.routine = routine
-        self.code = code
-
 class NoInit(object):
     def __init__(self):
-        raise CLRuntimeError("This class cannot be instantiated.")
+        raise RuntimeError("This class cannot be instantiated.")
 
 def get_cl_header_version():
     v = _lib.get_cl_version()
     return (v >> (3*4),
             (v >> (1*4)) & 0xff)
-        
+
+
+
 # {{{ expose constants classes like platform_info, device_type, ...
 _constants = {}
-@_ffi.callback('void(const char*, const char* name, unsigned int value)')
+@_ffi.callback('void(const char*, const char* name, long value)')
 def _constant_callback(type_, name, value):
     s_type = _ffi.string(type_)
     _constants.setdefault(s_type, {})
@@ -142,6 +136,37 @@ for type_, d in _constants.iteritems():
     locals()[type_] = type(type_, (NoInit,), d)
 # }}}
 
+
+# {{{ exceptions
+
+class Error(Exception):
+    def __init__(self, routine, code, msg=""):
+        self.routine = routine
+        self.code = code
+        self.what = msg
+        super(Error, self).__init__(self, msg)
+        
+class MemoryError(Error):
+    pass
+class LogicError(Error):
+    pass
+class RuntimeError(Error):
+    pass
+
+def _handle_error(error):
+    if error == _ffi.NULL:
+        return
+    if error.code == status_code.MEM_OBJECT_ALLOCATION_FAILURE:
+        klass = MemoryError
+    elif error.code <= status_code.INVALID_VALUE:
+        klass = LogicError
+    elif status_code.INVALID_VALUE < error.code < status_code.SUCCESS:
+        klass = RuntimeError
+    else:
+        klass = Error
+    raise klass(_ffi.string(error.routine), error.code, _ffi.string(error.msg))
+# }}}
+
 class EQUALITY_TESTS(object):
     def __eq__(self, other):
         return hash(self) == hash(other)
@@ -159,7 +184,7 @@ class Device(EQUALITY_TESTS):
         if param == 4145:
             return self.__dict__["platform"] # TODO HACK
         info = _ffi.new('generic_info *')
-        _lib.device__get_info(self.ptr, param, info)
+        _handle_error(_lib.device__get_info(self.ptr, param, info))
         return _generic_info_to_python(info)
 
 def _create_device(ptr):
@@ -174,14 +199,14 @@ def _parse_context_properties(properties):
 
     for prop_tuple in properties:
         if len(prop_tuple) != 2:
-            raise CLRuntimeError("Context", _lib.CL_INVALID_VALUE, "property tuple must have length 2")
+            raise RuntimeError("Context", status_code.INVALID_VALUE, "property tuple must have length 2")
         prop, value = prop_tuple
         props.append(prop)
         if prop == _lib.CL_CONTEXT_PLATFORM:
             props.append(_ffi.cast('cl_context_properties', value.data()))
             
         else: # TODO_PLAT CL_WGL_HDC_KHR and morecc
-            raise CLRuntimeError("Context", _lib.CL_INVALID_VALUE, "invalid context property")
+            raise RuntimeError("Context", status_code.INVALID_VALUE, "invalid context property")
     props.append(0)
     return _ffi.new('cl_context_properties[]', props)
 
@@ -194,10 +219,10 @@ class Context(EQUALITY_TESTS):
         # from device list
         if devices is not None:
             if dev_type is not None:
-                raise CLRuntimeError("Context", _lib.CL_INVALID_VALUE, "one of 'devices' or 'dev_type' must be None")
+                raise RuntimeError("Context", status_code.INVALID_VALUE, "one of 'devices' or 'dev_type' must be None")
             ptr_devices = _ffi.new('cl_device_id[]', [device.ptr for device in devices])
             ptr_ctx = _ffi.new('void **')
-            _lib._create_context(ptr_ctx, c_props, len(ptr_devices), _ffi.cast('void**', ptr_devices))
+            _handle_error(_lib._create_context(ptr_ctx, c_props, len(ptr_devices), _ffi.cast('void**', ptr_devices)))
             
         else: # from dev_type
             raise NotImplementedError()
@@ -215,7 +240,7 @@ class CommandQueue(EQUALITY_TESTS):
         if properties is None:
             properties = 0
         ptr_command_queue = _ffi.new('void **')
-        _lib._create_command_queue(ptr_command_queue, context.ptr, _ffi.NULL if device is None else device.ptr, properties)
+        _handle_error(_lib._create_command_queue(ptr_command_queue, context.ptr, _ffi.NULL if device is None else device.ptr, properties))
         self.ptr = ptr_command_queue[0]
 
     def __hash__(self):
@@ -228,7 +253,7 @@ class CommandQueue(EQUALITY_TESTS):
 class MemoryObjectHolder(EQUALITY_TESTS):
     def get_info(self, param):
         info = _ffi.new('generic_info *')
-        _lib.memory_object_holder__get_info(self.ptr, param, info)
+        _handle_error(_lib.memory_object_holder__get_info(self.ptr, param, info))
         return _generic_info_to_python(info)
 
     def __hash__(self):
@@ -247,12 +272,12 @@ class Buffer(MemoryObjectHolder):
             c_hostbuf = _ffi.cast('void *', hostbuf.ctypes.data)
             hostbuf_size = hostbuf.nbytes
             if size > hostbuf_size:
-                raise CLRuntimeError("Buffer", _lib.CL_INVALID_VALUE, "specified size is greater than host buffer size")
+                raise RuntimeError("Buffer", status_code.INVALID_VALUE, "specified size is greater than host buffer size")
             if size == 0:
                 size = hostbuf_size
 
         ptr_buffer = _ffi.new('void **')
-        _lib._create_buffer(ptr_buffer, context.ptr, flags, size, c_hostbuf)
+        _handle_error(_lib._create_buffer(ptr_buffer, context.ptr, flags, size, c_hostbuf))
         self.ptr = ptr_buffer[0]
 
 class _Program(object):
@@ -273,24 +298,24 @@ class _Program(object):
             
     def _init_source(self, context, src):
         ptr_program = _ffi.new('void **')
-        _lib._create_program_with_source(ptr_program, context.ptr, _ffi.new('char[]', src))
+        _handle_error(_lib._create_program_with_source(ptr_program, context.ptr, _ffi.new('char[]', src)))
         self.ptr = ptr_program[0]
 
     def _init_binary(self, context, devices, binaries):
         if len(devices) != len(binaries):
-            raise CLRuntimeError("create_program_with_binary", _lib.CL_INVALID_VALUE, "device and binary counts don't match")
+            raise RuntimeError("create_program_with_binary", status_code.INVALID_VALUE, "device and binary counts don't match")
             
         ptr_program = _ffi.new('void **')
         ptr_devices = _ffi.new('void*[]', [device.ptr for device in devices])
         ptr_binaries = _ffi.new('char*[]', len(binaries))
         for i, binary in enumerate(binaries):
             ptr_binaries[i] = _ffi.new('char[]', binary)
-        _lib._create_program_with_binary(ptr_program, context.ptr, len(ptr_devices), ptr_devices, len(ptr_binaries), ptr_binaries)
+        _handle_error(_lib._create_program_with_binary(ptr_program, context.ptr, len(ptr_devices), ptr_devices, len(ptr_binaries), ptr_binaries))
         self.ptr = ptr_program[0]
 
     def kind(self):
         kind = _ffi.new('int *')
-        _lib.program__kind(self.ptr, kind)
+        _handle_error(_lib.program__kind(self.ptr, kind))
         return kind[0]
 
     def _build(self, options=None, devices=None):
@@ -299,13 +324,14 @@ class _Program(object):
         if options is None:
             options = ""
         ptr_devices = _ffi.new('void*[]', [device.ptr for device in devices])
-        _lib.program__build(self.ptr, _ffi.new('char[]', options), len(ptr_devices), _ffi.cast('void**', ptr_devices))
+        
+        _handle_error(_lib.program__build(self.ptr, _ffi.new('char[]', options), len(ptr_devices), _ffi.cast('void**', ptr_devices)))
 
     def get_info(self, param):
         if param == program_info.DEVICES:
             # todo: refactor, same code as in get_devices 
             devices = _CArray(_ffi.new('void**'))
-            _lib.program__get_info__devices(self.ptr, devices.ptr, devices.size)
+            _handle_error(_lib.program__get_info__devices(self.ptr, devices.ptr, devices.size))
             result = []
             for i in xrange(devices.size[0]):
                 # TODO why is the cast needed? 
@@ -314,7 +340,7 @@ class _Program(object):
             return result
         elif param == program_info.BINARIES:
             ptr_binaries = _CArrays(_ffi.new('char***'))
-            _lib.program__get_info__binaries(self.ptr, ptr_binaries.ptr, ptr_binaries.size)
+            _handle_error(_lib.program__get_info__binaries(self.ptr, ptr_binaries.ptr, ptr_binaries.size))
             return map(_ffi.string, ptr_binaries)
         print param
         raise NotImplementedError()
@@ -330,12 +356,12 @@ class Platform(EQUALITY_TESTS):
 
     def get_info(self, param):
         info = _ffi.new('generic_info *')
-        _lib.platform__get_info(self.ptr, param, info)
+        _handle_error(_lib.platform__get_info(self.ptr, param, info))
         return _generic_info_to_python(info)
     
     def get_devices(self, device_type=device_type.ALL):
         devices = _CArray(_ffi.new('void**'))
-        _lib.platform__get_devices(self.ptr, devices.ptr, devices.size, device_type)
+        _handle_error(_lib.platform__get_devices(self.ptr, devices.ptr, devices.size, device_type))
         result = []
         for i in xrange(devices.size[0]):
             # TODO why is the cast needed? 
@@ -364,7 +390,7 @@ def _generic_info_to_python(info):
 class Kernel(object):
     def __init__(self, program, name):
         ptr_kernel = _ffi.new('void **')
-        _lib._create_kernel(ptr_kernel, program.ptr, name)
+        _handle_error(_lib._create_kernel(ptr_kernel, program.ptr, name))
         self.ptr = ptr_kernel[0]
 
     def __hash__(self):
@@ -372,19 +398,19 @@ class Kernel(object):
         
     def get_info(self, param):
         info = _ffi.new('generic_info *')
-        _lib.kernel__get_info(self.ptr, param, info)
+        _handle_error(_lib.kernel__get_info(self.ptr, param, info))
         return _generic_info_to_python(info)
         #raise NotImplementedError()
 
     def set_arg(self, arg_index, arg):
         if isinstance(arg, Buffer):
-            _lib.kernel__set_arg_mem_buffer(self.ptr, arg_index, arg.ptr)
+            _handle_error(_lib.kernel__set_arg_mem_buffer(self.ptr, arg_index, arg.ptr))
         else:
             raise NotImplementedError()
     
 def get_platforms():
     platforms = _CArray(_ffi.new('void**'))
-    _lib.get_platforms(platforms.ptr, platforms.size)
+    _handle_error(_lib.get_platforms(platforms.ptr, platforms.size))
     result = []
     for i in xrange(platforms.size[0]):
         # TODO why is the cast needed? 
@@ -419,7 +445,7 @@ def enqueue_nd_range_kernel(queue, kernel, global_work_size, local_work_size, gl
         if g_times_l:
             work_dim = max(work_dim, len(local_work_size))
         elif work_dim != len(local_work_size):
-            raise CLRuntimeError("enqueue_nd_range_kernel", _lib.CL_INVALID_VALUE,
+            raise RuntimeError("enqueue_nd_range_kernel", status_code.INVALID_VALUE,
                                  "global/local work sizes have differing dimensions")
         
         local_work_size = list(local_work_size)
@@ -444,7 +470,7 @@ def enqueue_nd_range_kernel(queue, kernel, global_work_size, local_work_size, gl
         c_local_work_size = _ffi.new('const size_t[]', local_work_size)
 
     ptr_event = _ffi.new('void **')
-    _lib._enqueue_nd_range_kernel(
+    _handle_error(_lib._enqueue_nd_range_kernel(
         ptr_event,
         queue.ptr,
         kernel.ptr,
@@ -452,7 +478,7 @@ def enqueue_nd_range_kernel(queue, kernel, global_work_size, local_work_size, gl
         c_global_work_offset,
         c_global_work_size,
         c_local_work_size
-    )
+    ))
     return _create_event(ptr_event[0])
 
 def _enqueue_read_buffer(cq, mem, buf, device_offset=0, is_blocking=True):
@@ -460,7 +486,7 @@ def _enqueue_read_buffer(cq, mem, buf, device_offset=0, is_blocking=True):
     c_buf = _ffi.cast('void *', buf.ctypes.data)
     size = buf.nbytes
     ptr_event = _ffi.new('void **')
-    _lib._enqueue_read_buffer(
+    _handle_error(_lib._enqueue_read_buffer(
         ptr_event,
         cq.ptr,
         mem.ptr,
@@ -468,8 +494,5 @@ def _enqueue_read_buffer(cq, mem, buf, device_offset=0, is_blocking=True):
         size,
         device_offset,
         bool(is_blocking)
-    )
+    ))
     return _create_event(ptr_event[0])
-
-
-
diff --git a/src/c_wrapper/wrap_cl.cpp b/src/c_wrapper/wrap_cl.cpp
index 3619fa9e3dd7596b2c8b2c3c190c04fb2fe612c3..c09f05242e58146b27341cb3dbb9a4c6d9adf93c 100644
--- a/src/c_wrapper/wrap_cl.cpp
+++ b/src/c_wrapper/wrap_cl.cpp
@@ -19,6 +19,17 @@
 #define PYOPENCL_PRINT_CALL_TRACE_INFO(NAME, EXTRA_INFO) /*nothing*/
 #endif
 
+#define C_HANDLE_ERROR(OPERATION)		\
+  try {						\
+    OPERATION					\
+      } catch(pyopencl::error& e) {		\
+    MALLOC(::error, error, 1);			\
+    error->routine = e.routine();		\
+    error->msg = e.what();			\
+    error->code = e.code();			\
+    return error;				\
+  }						
+
 // TODO Py_BEGIN_ALLOW_THREADS \ Py_END_ALLOW_THREADS below
 #define PYOPENCL_CALL_GUARDED_THREADED(NAME, ARGLIST)	\
   {							\
@@ -190,7 +201,6 @@ namespace pyopencl
     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;
@@ -1946,6 +1956,7 @@ inline event *enqueue_nd_range_kernel(
   
 
   void *get_platforms(void **ptr_platforms, uint32_t *num_platforms) {
+    C_HANDLE_ERROR(
     *num_platforms = 0;
     PYOPENCL_CALL_GUARDED(clGetPlatformIDs, (0, 0, num_platforms));
 
@@ -1959,6 +1970,7 @@ inline event *enqueue_nd_range_kernel(
       _ptr_platforms[i] = new platform(platforms[i]);
     }
     *ptr_platforms = _ptr_platforms;
+		   )
     return 0;
   }
 
@@ -1973,16 +1985,15 @@ inline event *enqueue_nd_range_kernel(
   }
 
   void *platform__get_info(void *ptr_platform, cl_platform_info param, generic_info *out) {
-    // todo: catch error
+    C_HANDLE_ERROR(
     *out = static_cast<platform*>(ptr_platform)->get_info(param);
-    //*out = _copy_str(static_cast<platform*>(ptr_platform)->get_info(param_name));
+		   )
     return 0;
   }
 
   void *platform__get_devices(void *ptr_platform, void **ptr_devices, uint32_t *num_devices, cl_device_type devtype) {
     typedef std::vector<cl_device_id> vec;
-    
-    // todo: catch error
+    C_HANDLE_ERROR(
     vec devices = static_cast<platform*>(ptr_platform)->get_devices(devtype);
     *num_devices = devices.size();
 
@@ -1991,7 +2002,7 @@ inline event *enqueue_nd_range_kernel(
       _ptr_devices[i] = new device(devices[i]);
     }
     *ptr_devices = _ptr_devices;
-    
+		   )
     return 0;
   }
   
@@ -2001,13 +2012,14 @@ inline event *enqueue_nd_range_kernel(
 
 
   void *device__get_info(void *ptr_device, cl_device_info param, generic_info *out) {
-    // todo: catch error
+    C_HANDLE_ERROR(
     *out = static_cast<device*>(ptr_device)->get_info(param);
+		   )
     return 0;
   }
 
   void *_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) {
@@ -2018,64 +2030,67 @@ inline event *enqueue_nd_range_kernel(
 				     devices.empty() ? NULL : &devices.front(),
 				     0, 0, &status_code);
     if (status_code != CL_SUCCESS) {
-      std::cout << status_code << std::endl;
-      // TODO error handling
-      //throw pyopencl::error("Context", status_code);
+      throw pyopencl::error("Context", status_code);
     }
     *ptr_ctx = new context(ctx, false);
-    
+		   )
     return 0;
   }
 
   void *_create_command_queue(void **ptr_command_queue, void *ptr_context, void *ptr_device, cl_command_queue_properties properties) {
-    // todo error handling
     context *ctx = static_cast<context*>(ptr_context);
     device *dev = static_cast<device*>(ptr_device);
+    C_HANDLE_ERROR(
     *ptr_command_queue = new command_queue(*ctx, dev, properties);
+		   )
     return 0;
   }
 
   void *_create_buffer(void **ptr_buffer, void *ptr_context, cl_mem_flags flags, size_t size, void *hostbuf) {
     context *ctx = static_cast<context*>(ptr_context);
+    C_HANDLE_ERROR(
     *ptr_buffer = create_buffer_py(*ctx, flags, size, hostbuf);
-    // todo error handling
+		   )
     return 0;
   }
 
   void *_create_program_with_source(void **ptr_program, void *ptr_context, char *src) {
     context *ctx = static_cast<context*>(ptr_context);
+    C_HANDLE_ERROR(
     *ptr_program = create_program_with_source(*ctx, src);
-    // todo error handling
+		   )
     return 0;
   }
 
   void *_create_program_with_binary(void **ptr_program, void *ptr_context, cl_uint num_devices, void **ptr_devices, cl_uint num_binaries, char **binaries) {
-    // todo: catch error
     context *ctx = static_cast<context*>(ptr_context);
+    C_HANDLE_ERROR(
     *ptr_program = create_program_with_binary(*ctx, num_devices, ptr_devices, num_binaries, binaries);
+		   )
     return 0;
   }
 
-  void *program__build(void *ptr_program, char *options, cl_uint num_devices, void **ptr_devices) {
-    // todo: catch error
-    static_cast<program*>(ptr_program)->build(options, num_devices, ptr_devices);
+  ::error *program__build(void *ptr_program, char *options, cl_uint num_devices, void **ptr_devices) {
+    C_HANDLE_ERROR(
+		   static_cast<program*>(ptr_program)->build(options, num_devices, ptr_devices);
+		   )
     return 0;
   }
 
   void *program__kind(void *ptr_program, int *kind) {
-    // todo: catch error
-    *kind = static_cast<program*>(ptr_program)->kind();
+    C_HANDLE_ERROR(
+		   *kind = static_cast<program*>(ptr_program)->kind();
+		   )
     return 0;
   }
 
   void *program__get_info__devices(void *ptr_program, void **ptr_devices, uint32_t *num_devices) {
-
     typedef std::vector<cl_device_id> vec;
 
     // todo: refactor, same as get_devices()
-    
-    // todo: catch error
+    C_HANDLE_ERROR(
     vec devices = static_cast<program*>(ptr_program)->get_info__devices();
+		   
     *num_devices = devices.size();
 
     MALLOC(device*, _ptr_devices, *num_devices);
@@ -2083,14 +2098,15 @@ inline event *enqueue_nd_range_kernel(
       _ptr_devices[i] = new device(devices[i]);
     }
     *ptr_devices = _ptr_devices;
-    
+    )
     return 0;
     
   }
 
   void *program__get_info__binaries(void *ptr_program, char ***ptr_binaries, uint32_t *num_binaries) {
-    // todo catch error
+    C_HANDLE_ERROR(
     *ptr_binaries = static_cast<program*>(ptr_program)->get_info__binaries(num_binaries);
+		   )
     return 0;
   }
   
@@ -2125,48 +2141,53 @@ inline event *enqueue_nd_range_kernel(
   
   void *_create_kernel(void **ptr_kernel, void *ptr_program, char *name) {
     program *prg = static_cast<program*>(ptr_program);
+    C_HANDLE_ERROR(
     *ptr_kernel = new kernel(*prg, name);
-    // todo error handling
+		   )
     return 0;
   }
 
   void *kernel__get_info(void *ptr_kernel, cl_kernel_info param, generic_info *out) {
+    C_HANDLE_ERROR(
     *out = static_cast<kernel*>(ptr_kernel)->get_info(param);
-    // todo error handling
+		   )
     return 0;
   }
 
   void *kernel__set_arg_mem_buffer(void *ptr_kernel, cl_uint arg_index, void *ptr_buffer) {
     buffer *buf = static_cast<buffer*>(ptr_buffer);
+    C_HANDLE_ERROR(
     static_cast<kernel*>(ptr_kernel)->set_arg_mem(arg_index, *buf);
-    // todo error handling
+		   )
     return 0;
   }
 
   void *_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<command_queue*>(ptr_command_queue),
 					 *static_cast<kernel*>(ptr_kernel),
 					 work_dim,
 					 global_work_offset,
 					 global_work_size,
 					 local_work_size);
-    // todo error handling
-    
+		   )    
     return 0;
   }
 
 
   void *_enqueue_read_buffer(void **ptr_event, void *ptr_command_queue, void *ptr_memory_object_holder, void *buffer, size_t size, size_t device_offset, int is_blocking) {
+    C_HANDLE_ERROR(
     *ptr_event = enqueue_read_buffer(*static_cast<command_queue*>(ptr_command_queue),
 				     *static_cast<memory_object_holder*>(ptr_memory_object_holder),
 				     buffer, size, device_offset, (bool)is_blocking);
-    // todo error handling
+		   )
     return 0;
   }
   
   void *memory_object_holder__get_info(void *ptr_memory_object_holder, cl_mem_info param, generic_info *out) {
+    C_HANDLE_ERROR(
     *out = static_cast<memory_object_holder*>(ptr_memory_object_holder)->get_info(param);
-    // todo error handling
+		   )
     return 0;
   }
   
diff --git a/src/c_wrapper/wrap_cl_core.h b/src/c_wrapper/wrap_cl_core.h
index 1a48511ae07e8080889f3f184541861cca15db36..c109c9a17a6d1431205c44c15e659b3942da5024 100644
--- a/src/c_wrapper/wrap_cl_core.h
+++ b/src/c_wrapper/wrap_cl_core.h
@@ -15,6 +15,12 @@ typedef struct {
   } value;
 } generic_info;
 
+typedef struct {
+  const char *routine;
+  const char *msg;
+  cl_int code;
+} error;
+
 int get_cl_version(void);
 void *get_platforms(void **ptr_platforms, uint32_t *num_platforms);
 void *platform__get_info(void *ptr_platform, cl_platform_info param_name, generic_info *out);
@@ -30,7 +36,7 @@ void *_create_command_queue(void **ptr_command_queue, void *ptr_context, void *p
 void *_create_buffer(void **ptr_buffer, void *ptr_context, cl_mem_flags flags, size_t size, void *hostbuf);
 void *_create_program_with_source(void **ptr_program, void *ptr_context, char *src);
 void *_create_program_with_binary(void **ptr_program, void *ptr_context, cl_uint num_devices, void **ptr_devices, cl_uint num_binaries, char **binaries);
-void *program__build(void *ptr_program, char *options, cl_uint num_devices, void **ptr_devices);
+error *program__build(void *ptr_program, char *options, cl_uint num_devices, void **ptr_devices);
 void *program__kind(void *ptr_program, int *kind);
 void *program__get_info__devices(void *ptr_program, void **ptr_devices, uint32_t *num_devices);
 void *program__get_info__binaries(void *ptr_program, char ***ptr_binaries, uint32_t *num_binaries);
@@ -43,7 +49,7 @@ void *_enqueue_nd_range_kernel(void **ptr_event, void *ptr_command_queue, void *
 void *_enqueue_read_buffer(void **ptr_event, void *ptr_command_queue, void *ptr_memory_object_holder, void *buffer, size_t size, size_t device_offset, int is_blocking);
 void *memory_object_holder__get_info(void *ptr_memory_object_holder, cl_mem_info param, generic_info *out);
 long memory_object_holder__hash(void *ptr_memory_object_holder);
-void populate_constants(void(*add)(const char*, const char*, unsigned int value));
+void populate_constants(void(*add)(const char*, const char*, long value));
 void _free(void*);
 void _free2(void**, uint32_t size);
 
diff --git a/src/c_wrapper/wrap_constants.cpp b/src/c_wrapper/wrap_constants.cpp
index a994a7c58659a493a035742b0c85476a654e29c6..ed6e1f7c98b9c3a7c39efb8dd6bb49c7ccdac672 100644
--- a/src/c_wrapper/wrap_constants.cpp
+++ b/src/c_wrapper/wrap_constants.cpp
@@ -1,8 +1,9 @@
 #include "wrap_cl.h"
+#include <iostream>
 
 extern "C"
 namespace pyopencl {
-  void populate_constants(void(*add)(const char*, const char*, unsigned int value)) {
+  void populate_constants(void(*add)(const char*, const char*, long value)) {
 #define ADD_ATTR(TYPE, PREFIX, NAME)		\
     add(TYPE, #NAME, CL_##PREFIX##NAME)