From a2d71628f6429a795a59d94937d121c2fa70034a Mon Sep 17 00:00:00 2001
From: Marko Bencun <mbencun@gmail.com>
Date: Sat, 7 Sep 2013 21:23:02 +0200
Subject: [PATCH] convert non-pyopencl exceptions as well

---
 pyopencl/cffi_cl.py          | 14 +++++++++++++-
 src/c_wrapper/wrap_cl.cpp    | 34 +++++++++++++++++++++++-----------
 src/c_wrapper/wrap_cl_core.h |  1 +
 3 files changed, 37 insertions(+), 12 deletions(-)

diff --git a/pyopencl/cffi_cl.py b/pyopencl/cffi_cl.py
index 19b08cd2..f4a3119f 100644
--- a/pyopencl/cffi_cl.py
+++ b/pyopencl/cffi_cl.py
@@ -12,7 +12,8 @@ class _CArray(object):
         self.size = _ffi.new('uint32_t *')
 
     def __del__(self):
-        _lib._free(self.ptr[0])
+        if self.ptr != _ffi.NULL:
+            _lib._free(self.ptr[0])
 
     def __getitem__(self, key):
         return self.ptr[0].__getitem__(key)
@@ -70,6 +71,13 @@ class RuntimeError(Error):
 def _handle_error(error):
     if error == _ffi.NULL:
         return
+    if error.other == 1:
+        # non-pyopencl exceptions are handled here
+        import exceptions
+        e = exceptions.RuntimeError(_ffi.string(error.msg))
+        _lib._free(error.msg)
+        _lib._free(error)
+        raise e
     if error.code == status_code.MEM_OBJECT_ALLOCATION_FAILURE:
         klass = MemoryError
     elif error.code <= status_code.INVALID_VALUE:
@@ -79,11 +87,15 @@ def _handle_error(error):
     else:
         klass = Error
     e = klass(_ffi.string(error.routine), error.code, _ffi.string(error.msg))
+    _lib._free(error.routine)
+    _lib._free(error.msg)
     _lib._free(error)
     raise e
 # }}}
 
 class _Common(object):
+    ptr = _ffi.NULL
+    
     @classmethod
     def _c_class_type(cls):
         return getattr(_lib, 'CLASS_%s' % cls._id.upper())
diff --git a/src/c_wrapper/wrap_cl.cpp b/src/c_wrapper/wrap_cl.cpp
index acd2eb62..7b967e2d 100644
--- a/src/c_wrapper/wrap_cl.cpp
+++ b/src/c_wrapper/wrap_cl.cpp
@@ -21,16 +21,25 @@
 #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;				\
-  }						
+#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)	\
@@ -312,7 +321,8 @@ namespace pyopencl
 {
   char *_copy_str(const std::string& str) {
     MALLOC(char, cstr, str.size() + 1);
-    strcpy(cstr, str.c_str());
+    std::size_t len = str.copy(cstr, str.size());
+    cstr[len] = '\0';
     return cstr;
   }
   
@@ -1648,8 +1658,10 @@ namespace pyopencl
       cl_int status_code;
 
       PYOPENCL_PRINT_CALL_TRACE("clCreateKernel");
+      std::cout << "HUH HAHAH" << std::endl;
       m_kernel = clCreateKernel(prg.data(), kernel_name.c_str(),
 				&status_code);
+      std::cout << "HU2" << std::endl;
       if (status_code != CL_SUCCESS)
 	throw pyopencl::error("clCreateKernel", status_code);
     }
diff --git a/src/c_wrapper/wrap_cl_core.h b/src/c_wrapper/wrap_cl_core.h
index efac2d69..1a9ee937 100644
--- a/src/c_wrapper/wrap_cl_core.h
+++ b/src/c_wrapper/wrap_cl_core.h
@@ -4,6 +4,7 @@ typedef struct {
   const char *routine;
   const char *msg;
   cl_int code;
+  int other;
 } error;
 
 typedef enum {
-- 
GitLab