diff --git a/src/c_wrapper/buffer.cpp b/src/c_wrapper/buffer.cpp
index b506b8e7ecf07bbc64ee4f96ef6b6ddd02d8d1be..75480398e72dbe3e24351cee0589a77fb7111769 100644
--- a/src/c_wrapper/buffer.cpp
+++ b/src/c_wrapper/buffer.cpp
@@ -18,7 +18,7 @@ buffer::get_sub_region(size_t orig, size_t size, cl_mem_flags flags) const
     cl_buffer_region reg = {orig, size};
 
     auto mem = retry_mem_error([&] {
-            return pyopencl_call_guarded(clCreateSubBuffer, this, flags,
+            return pyopencl_call_guarded(clCreateSubBuffer, PYOPENCL_CL_CASTABLE_THIS, flags,
                                          CL_BUFFER_CREATE_TYPE_REGION, &reg);
         });
     return new_buffer(mem);
diff --git a/src/c_wrapper/command_queue.cpp b/src/c_wrapper/command_queue.cpp
index e56beea21be4ee59321c89391f6d770ad4f32424..a897540adb536ed1d8d4ff45fcf2deb5c038c0eb 100644
--- a/src/c_wrapper/command_queue.cpp
+++ b/src/c_wrapper/command_queue.cpp
@@ -13,7 +13,7 @@ template void print_buf<cl_command_queue>(
 
 command_queue::~command_queue()
 {
-    pyopencl_call_guarded_cleanup(clReleaseCommandQueue, this);
+    pyopencl_call_guarded_cleanup(clReleaseCommandQueue, PYOPENCL_CL_CASTABLE_THIS);
 }
 
 generic_info
@@ -22,15 +22,15 @@ command_queue::get_info(cl_uint param_name) const
     switch ((cl_command_queue_info)param_name) {
     case CL_QUEUE_CONTEXT:
         return pyopencl_get_opaque_info(context, CommandQueue,
-                                        this, param_name);
+                                        PYOPENCL_CL_CASTABLE_THIS, param_name);
     case CL_QUEUE_DEVICE:
-        return pyopencl_get_opaque_info(device, CommandQueue, this, param_name);
+        return pyopencl_get_opaque_info(device, CommandQueue, PYOPENCL_CL_CASTABLE_THIS, param_name);
     case CL_QUEUE_REFERENCE_COUNT:
         return pyopencl_get_int_info(cl_uint, CommandQueue,
-                                     this, param_name);
+                                     PYOPENCL_CL_CASTABLE_THIS, param_name);
     case CL_QUEUE_PROPERTIES:
         return pyopencl_get_int_info(cl_command_queue_properties,
-                                     CommandQueue, this, param_name);
+                                     CommandQueue, PYOPENCL_CL_CASTABLE_THIS, param_name);
     default:
         throw clerror("CommandQueue.get_info", CL_INVALID_VALUE);
     }
diff --git a/src/c_wrapper/command_queue.h b/src/c_wrapper/command_queue.h
index 378666fa0bb3e311d735434622a425272fc1514b..3a7c01710133f90c40e3afab58abc96f88277f86 100644
--- a/src/c_wrapper/command_queue.h
+++ b/src/c_wrapper/command_queue.h
@@ -19,7 +19,7 @@ public:
         : clobj(q)
     {
         if (retain) {
-            pyopencl_call_guarded(clRetainCommandQueue, this);
+            pyopencl_call_guarded(clRetainCommandQueue, PYOPENCL_CL_CASTABLE_THIS);
         }
     }
     PYOPENCL_INLINE
diff --git a/src/c_wrapper/context.cpp b/src/c_wrapper/context.cpp
index 11f68345078693a7e0334cfb153e5435ae9c6ee9..0a453d0ba797d396e1cdd2cd2ede6195f3d498e6 100644
--- a/src/c_wrapper/context.cpp
+++ b/src/c_wrapper/context.cpp
@@ -33,7 +33,7 @@ context::get_version(cl_context ctx, int *major, int *minor)
 
 context::~context()
 {
-    pyopencl_call_guarded_cleanup(clReleaseContext, this);
+    pyopencl_call_guarded_cleanup(clReleaseContext, PYOPENCL_CL_CASTABLE_THIS);
 }
 
 generic_info
@@ -42,13 +42,13 @@ context::get_info(cl_uint param_name) const
     switch ((cl_context_info)param_name) {
     case CL_CONTEXT_REFERENCE_COUNT:
         return pyopencl_get_int_info(cl_uint, Context,
-                                     this, param_name);
+                                     PYOPENCL_CL_CASTABLE_THIS, param_name);
     case CL_CONTEXT_DEVICES:
         return pyopencl_get_opaque_array_info(device, Context,
-                                              this, param_name);
+                                              PYOPENCL_CL_CASTABLE_THIS, param_name);
     case CL_CONTEXT_PROPERTIES: {
         auto result = pyopencl_get_vec_info(
-            cl_context_properties, Context, this, param_name);
+            cl_context_properties, Context, PYOPENCL_CL_CASTABLE_THIS, param_name);
         pyopencl_buf<generic_info> py_result(result.len() / 2);
         size_t i = 0;
         for (;i < py_result.len();i++) {
@@ -96,7 +96,7 @@ context::get_info(cl_uint param_name) const
 #if PYOPENCL_CL_VERSION >= 0x1010
     case CL_CONTEXT_NUM_DEVICES:
         return pyopencl_get_int_info(cl_uint, Context,
-                                     this, param_name);
+                                     PYOPENCL_CL_CASTABLE_THIS, param_name);
 #endif
 
     default:
diff --git a/src/c_wrapper/context.h b/src/c_wrapper/context.h
index ff94ecb18527421927703be3563e53605addd1f4..1691035d09fb5628c0bbda967c205f30a4882100 100644
--- a/src/c_wrapper/context.h
+++ b/src/c_wrapper/context.h
@@ -20,7 +20,7 @@ public:
         : clobj(ctx)
     {
         if (retain) {
-            pyopencl_call_guarded(clRetainContext, this);
+            pyopencl_call_guarded(clRetainContext, PYOPENCL_CL_CASTABLE_THIS);
         }
     }
     ~context();
diff --git a/src/c_wrapper/device.cpp b/src/c_wrapper/device.cpp
index c4a62a16431c0a6c03873f47bfca040d27f71c3a..39ebfd0f2cbd99e541501d129f82554edcf07e05 100644
--- a/src/c_wrapper/device.cpp
+++ b/src/c_wrapper/device.cpp
@@ -23,7 +23,7 @@ device::~device()
     }
 #if PYOPENCL_CL_VERSION >= 0x1020
     else if (m_ref_type == REF_CL_1_2) {
-        pyopencl_call_guarded_cleanup(clReleaseDevice, this);
+        pyopencl_call_guarded_cleanup(clReleaseDevice, PYOPENCL_CL_CASTABLE_THIS);
     }
 #endif
 }
@@ -32,7 +32,7 @@ generic_info
 device::get_info(cl_uint param_name) const
 {
 #define DEV_GET_INT_INF(TYPE)                                   \
-    pyopencl_get_int_info(TYPE, Device, this, param_name)
+    pyopencl_get_int_info(TYPE, Device, PYOPENCL_CL_CASTABLE_THIS, param_name)
 
     switch ((cl_device_info)param_name) {
     case CL_DEVICE_TYPE:
@@ -45,7 +45,7 @@ device::get_info(cl_uint param_name) const
         return DEV_GET_INT_INF(cl_uint);
 
     case CL_DEVICE_MAX_WORK_ITEM_SIZES:
-        return pyopencl_get_array_info(size_t, Device, this, param_name);
+        return pyopencl_get_array_info(size_t, Device, PYOPENCL_CL_CASTABLE_THIS, param_name);
 
     case CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR:
     case CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT:
@@ -118,10 +118,10 @@ device::get_info(cl_uint param_name) const
     case CL_DEVICE_PROFILE:
     case CL_DEVICE_VERSION:
     case CL_DEVICE_EXTENSIONS:
-        return pyopencl_get_str_info(Device, this, param_name);
+        return pyopencl_get_str_info(Device, PYOPENCL_CL_CASTABLE_THIS, param_name);
 
     case CL_DEVICE_PLATFORM:
-        return pyopencl_get_opaque_info(platform, Device, this, param_name);
+        return pyopencl_get_opaque_info(platform, Device, PYOPENCL_CL_CASTABLE_THIS, param_name);
 #if PYOPENCL_CL_VERSION >= 0x1010
     case CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF:
     case CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR:
@@ -136,7 +136,7 @@ device::get_info(cl_uint param_name) const
     case CL_DEVICE_HOST_UNIFIED_MEMORY: // deprecated in 2.0
         return DEV_GET_INT_INF(cl_bool);
     case CL_DEVICE_OPENCL_C_VERSION:
-        return pyopencl_get_str_info(Device, this, param_name);
+        return pyopencl_get_str_info(Device, PYOPENCL_CL_CASTABLE_THIS, param_name);
 #endif
 #ifdef CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV
     case CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV:
@@ -153,21 +153,21 @@ device::get_info(cl_uint param_name) const
     case CL_DEVICE_LINKER_AVAILABLE:
         return DEV_GET_INT_INF(cl_bool);
     case CL_DEVICE_BUILT_IN_KERNELS:
-        return pyopencl_get_str_info(Device, this, param_name);
+        return pyopencl_get_str_info(Device, PYOPENCL_CL_CASTABLE_THIS, param_name);
     case CL_DEVICE_IMAGE_MAX_BUFFER_SIZE:
     case CL_DEVICE_IMAGE_MAX_ARRAY_SIZE:
         return DEV_GET_INT_INF(size_t);
     case CL_DEVICE_PARENT_DEVICE:
-        return pyopencl_get_opaque_info(device, Device, this, param_name);
+        return pyopencl_get_opaque_info(device, Device, PYOPENCL_CL_CASTABLE_THIS, param_name);
     case CL_DEVICE_PARTITION_MAX_SUB_DEVICES:
         return DEV_GET_INT_INF(cl_uint);
     case CL_DEVICE_PARTITION_TYPE:
     case CL_DEVICE_PARTITION_PROPERTIES:
         return pyopencl_get_array_info(cl_device_partition_property,
-                                       Device, this, param_name);
+                                       Device, PYOPENCL_CL_CASTABLE_THIS, param_name);
     case CL_DEVICE_PARTITION_AFFINITY_DOMAIN:
         return pyopencl_get_array_info(cl_device_affinity_domain,
-                                       Device, this, param_name);
+                                       Device, PYOPENCL_CL_CASTABLE_THIS, param_name);
     case CL_DEVICE_REFERENCE_COUNT:
         return DEV_GET_INT_INF(cl_uint);
     case CL_DEVICE_PREFERRED_INTEROP_USER_SYNC:
@@ -225,12 +225,12 @@ device::get_info(cl_uint param_name) const
         */
 #ifdef CL_DEVICE_BOARD_NAME_AMD
     case CL_DEVICE_BOARD_NAME_AMD: ;
-        return pyopencl_get_str_info(Device, this, param_name);
+        return pyopencl_get_str_info(Device, PYOPENCL_CL_CASTABLE_THIS, param_name);
 #endif
 #ifdef CL_DEVICE_GLOBAL_FREE_MEMORY_AMD
     case CL_DEVICE_GLOBAL_FREE_MEMORY_AMD:
         return pyopencl_get_array_info(size_t, Device,
-                                       this, param_name);
+                                       PYOPENCL_CL_CASTABLE_THIS, param_name);
 #endif
 #ifdef CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD
     case CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD:
@@ -277,10 +277,10 @@ device::create_sub_devices(const cl_device_partition_property *props)
 {
     // TODO debug print props
     cl_uint num_devices;
-    pyopencl_call_guarded(clCreateSubDevices, this, props, 0, nullptr,
+    pyopencl_call_guarded(clCreateSubDevices, PYOPENCL_CL_CASTABLE_THIS, props, 0, nullptr,
                           buf_arg(num_devices));
     pyopencl_buf<cl_device_id> devices(num_devices);
-    pyopencl_call_guarded(clCreateSubDevices, this, props, devices,
+    pyopencl_call_guarded(clCreateSubDevices, PYOPENCL_CL_CASTABLE_THIS, props, devices,
                           buf_arg(num_devices));
     return buf_to_base<device>(devices, true, device::REF_CL_1_2);
 }
diff --git a/src/c_wrapper/device.h b/src/c_wrapper/device.h
index a74ce5a5531e1c69b58e0e96ea531479a43626fe..a14a946804f0c116a683548068960d2a19db3df2 100644
--- a/src/c_wrapper/device.h
+++ b/src/c_wrapper/device.h
@@ -33,7 +33,7 @@ public:
             }
 #if PYOPENCL_CL_VERSION >= 0x1020
             else if (ref_type == REF_CL_1_2) {
-                pyopencl_call_guarded(clRetainDevice, this);
+                pyopencl_call_guarded(clRetainDevice, PYOPENCL_CL_CASTABLE_THIS);
             }
 #endif
 
diff --git a/src/c_wrapper/error.h b/src/c_wrapper/error.h
index 5e483698f58abd428598e5572102851fe77aaba6..3a7ed85e07d909d28a7771050235f2c8b256dab4 100644
--- a/src/c_wrapper/error.h
+++ b/src/c_wrapper/error.h
@@ -14,6 +14,14 @@
 
 // {{{ error
 
+// See https://github.com/pyopencl/pyopencl/pull/83
+#if GCC_VERSION > 50200
+#define PYOPENCL_CL_CASTABLE_THIS this
+#else
+#define PYOPENCL_CL_CASTABLE_THIS data()
+#endif
+
+
 class clerror : public std::runtime_error {
 private:
     const char *m_routine;
diff --git a/src/c_wrapper/event.cpp b/src/c_wrapper/event.cpp
index 63c6daa7186f2cb19eaaa98e12e02e5036cf43ed..6faf2b58dd7c076ae929487341626fe27ed647ad 100644
--- a/src/c_wrapper/event.cpp
+++ b/src/c_wrapper/event.cpp
@@ -40,7 +40,7 @@ event::event(cl_event event, bool retain, event_private *p)
 {
     if (retain) {
         try {
-            pyopencl_call_guarded(clRetainEvent, this);
+            pyopencl_call_guarded(clRetainEvent, PYOPENCL_CL_CASTABLE_THIS);
         } catch (...) {
             m_p->call_finish();
             delete m_p;
@@ -106,7 +106,7 @@ event::release_private() noexcept
 event::~event()
 {
     release_private();
-    pyopencl_call_guarded_cleanup(clReleaseEvent, this);
+    pyopencl_call_guarded_cleanup(clReleaseEvent, PYOPENCL_CL_CASTABLE_THIS);
 }
 
 generic_info
@@ -114,17 +114,17 @@ event::get_info(cl_uint param_name) const
 {
     switch ((cl_event_info)param_name) {
     case CL_EVENT_COMMAND_QUEUE:
-        return pyopencl_get_opaque_info(command_queue, Event, this, param_name);
+        return pyopencl_get_opaque_info(command_queue, Event, PYOPENCL_CL_CASTABLE_THIS, param_name);
     case CL_EVENT_COMMAND_TYPE:
         return pyopencl_get_int_info(cl_command_type, Event,
-                                     this, param_name);
+                                     PYOPENCL_CL_CASTABLE_THIS, param_name);
     case CL_EVENT_COMMAND_EXECUTION_STATUS:
-        return pyopencl_get_int_info(cl_int, Event, this, param_name);
+        return pyopencl_get_int_info(cl_int, Event, PYOPENCL_CL_CASTABLE_THIS, param_name);
     case CL_EVENT_REFERENCE_COUNT:
-        return pyopencl_get_int_info(cl_uint, Event, this, param_name);
+        return pyopencl_get_int_info(cl_uint, Event, PYOPENCL_CL_CASTABLE_THIS, param_name);
 #if PYOPENCL_CL_VERSION >= 0x1010
     case CL_EVENT_CONTEXT:
-        return pyopencl_get_opaque_info(context, Event, this, param_name);
+        return pyopencl_get_opaque_info(context, Event, PYOPENCL_CL_CASTABLE_THIS, param_name);
 #endif
 
     default:
@@ -140,7 +140,7 @@ event::get_profiling_info(cl_profiling_info param) const
     case CL_PROFILING_COMMAND_SUBMIT:
     case CL_PROFILING_COMMAND_START:
     case CL_PROFILING_COMMAND_END:
-        return pyopencl_get_int_info(cl_ulong, EventProfiling, this, param);
+        return pyopencl_get_int_info(cl_ulong, EventProfiling, PYOPENCL_CL_CASTABLE_THIS, param);
     default:
         throw clerror("Event.get_profiling_info", CL_INVALID_VALUE);
     }
@@ -195,7 +195,7 @@ public:
     PYOPENCL_INLINE void
     set_status(cl_int status)
     {
-        pyopencl_call_guarded(clSetUserEventStatus, this, status);
+        pyopencl_call_guarded(clSetUserEventStatus, PYOPENCL_CL_CASTABLE_THIS, status);
     }
 };
 #endif
diff --git a/src/c_wrapper/event.h b/src/c_wrapper/event.h
index 7c3b4852890050203803f13d48238c52f28359c7..3d6c8769d05d145a8b26fcd1fb8efbe59dcb3fc1 100644
--- a/src/c_wrapper/event.h
+++ b/src/c_wrapper/event.h
@@ -39,7 +39,7 @@ public:
         auto func = new rm_ref_t<Func>(std::forward<Func>(_func));
         try {
             pyopencl_call_guarded(
-                clSetEventCallback, this, type,
+                clSetEventCallback, PYOPENCL_CL_CASTABLE_THIS, type,
                 [] (cl_event, cl_int status, void *data) {
                     rm_ref_t<Func> *func = static_cast<rm_ref_t<Func>*>(data);
                     std::thread t([func, status] () {
diff --git a/src/c_wrapper/image.cpp b/src/c_wrapper/image.cpp
index 775528588046afa578aa5b9dcff1b76c3d1719af..427f1e344da3ebf15823974ac7c67d6cb1f4559e 100644
--- a/src/c_wrapper/image.cpp
+++ b/src/c_wrapper/image.cpp
@@ -17,7 +17,7 @@ image::get_image_info(cl_image_info param) const
 {
     switch (param) {
     case CL_IMAGE_FORMAT:
-        return pyopencl_get_int_info(cl_image_format, Image, this, param);
+        return pyopencl_get_int_info(cl_image_format, Image, PYOPENCL_CL_CASTABLE_THIS, param);
     case CL_IMAGE_ELEMENT_SIZE:
     case CL_IMAGE_ROW_PITCH:
     case CL_IMAGE_SLICE_PITCH:
@@ -27,7 +27,7 @@ image::get_image_info(cl_image_info param) const
 #if PYOPENCL_CL_VERSION >= 0x1020
     case CL_IMAGE_ARRAY_SIZE:
 #endif
-        return pyopencl_get_int_info(size_t, Image, this, param);
+        return pyopencl_get_int_info(size_t, Image, PYOPENCL_CL_CASTABLE_THIS, param);
 
 #if PYOPENCL_CL_VERSION >= 0x1020
         // TODO:
@@ -44,7 +44,7 @@ image::get_image_info(cl_image_info param) const
         //      }
     case CL_IMAGE_NUM_MIP_LEVELS:
     case CL_IMAGE_NUM_SAMPLES:
-        return pyopencl_get_int_info(cl_uint, Image, this, param);
+        return pyopencl_get_int_info(cl_uint, Image, PYOPENCL_CL_CASTABLE_THIS, param);
 #endif
     default:
         throw clerror("Image.get_image_info", CL_INVALID_VALUE);
diff --git a/src/c_wrapper/image.h b/src/c_wrapper/image.h
index 55520f8801eec093f15d778489e7b3a4d1cfaea6..7d29909c9d30896ae915cb32138561ab115f0950 100644
--- a/src/c_wrapper/image.h
+++ b/src/c_wrapper/image.h
@@ -19,7 +19,7 @@ public:
     format()
     {
         if (!m_format.image_channel_data_type) {
-            pyopencl_call_guarded(clGetImageInfo, this, CL_IMAGE_FORMAT,
+            pyopencl_call_guarded(clGetImageInfo, PYOPENCL_CL_CASTABLE_THIS, CL_IMAGE_FORMAT,
                                   size_arg(m_format), nullptr);
         }
         return m_format;
diff --git a/src/c_wrapper/kernel.cpp b/src/c_wrapper/kernel.cpp
index 80ab8c5ad92e72c09e2f4506d5c6c2d3987e9b10..9c268ed68cddb86e9e3b9d9a2118e2d45468b700 100644
--- a/src/c_wrapper/kernel.cpp
+++ b/src/c_wrapper/kernel.cpp
@@ -16,7 +16,7 @@ template void print_buf<cl_kernel>(std::ostream&, const cl_kernel*,
 
 kernel::~kernel()
 {
-    pyopencl_call_guarded_cleanup(clReleaseKernel, this);
+    pyopencl_call_guarded_cleanup(clReleaseKernel, PYOPENCL_CL_CASTABLE_THIS);
 }
 
 generic_info
@@ -24,17 +24,17 @@ kernel::get_info(cl_uint param) const
 {
     switch ((cl_kernel_info)param) {
     case CL_KERNEL_FUNCTION_NAME:
-        return pyopencl_get_str_info(Kernel, this, param);
+        return pyopencl_get_str_info(Kernel, PYOPENCL_CL_CASTABLE_THIS, param);
     case CL_KERNEL_NUM_ARGS:
     case CL_KERNEL_REFERENCE_COUNT:
-        return pyopencl_get_int_info(cl_uint, Kernel, this, param);
+        return pyopencl_get_int_info(cl_uint, Kernel, PYOPENCL_CL_CASTABLE_THIS, param);
     case CL_KERNEL_CONTEXT:
-        return pyopencl_get_opaque_info(context, Kernel, this, param);
+        return pyopencl_get_opaque_info(context, Kernel, PYOPENCL_CL_CASTABLE_THIS, param);
     case CL_KERNEL_PROGRAM:
-        return pyopencl_get_opaque_info(program, Kernel, this, param);
+        return pyopencl_get_opaque_info(program, Kernel, PYOPENCL_CL_CASTABLE_THIS, param);
 #if PYOPENCL_CL_VERSION >= 0x1020
     case CL_KERNEL_ATTRIBUTES:
-        return pyopencl_get_str_info(Kernel, this, param);
+        return pyopencl_get_str_info(Kernel, PYOPENCL_CL_CASTABLE_THIS, param);
 #endif
     default:
         throw clerror("Kernel.get_info", CL_INVALID_VALUE);
@@ -50,16 +50,16 @@ kernel::get_work_group_info(cl_kernel_work_group_info param,
     case CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE:
 #endif
     case CL_KERNEL_WORK_GROUP_SIZE:
-        return pyopencl_get_int_info(size_t, KernelWorkGroup, this, dev, param);
+        return pyopencl_get_int_info(size_t, KernelWorkGroup, PYOPENCL_CL_CASTABLE_THIS, dev, param);
     case CL_KERNEL_COMPILE_WORK_GROUP_SIZE:
         return pyopencl_get_array_info(size_t, KernelWorkGroup,
-                                       this, dev, param);
+                                       PYOPENCL_CL_CASTABLE_THIS, dev, param);
     case CL_KERNEL_LOCAL_MEM_SIZE:
 #if PYOPENCL_CL_VERSION >= 0x1010
     case CL_KERNEL_PRIVATE_MEM_SIZE:
 #endif
         return pyopencl_get_int_info(cl_ulong, KernelWorkGroup,
-                                     this, dev, param);
+                                     PYOPENCL_CL_CASTABLE_THIS, dev, param);
     default:
         throw clerror("Kernel.get_work_group_info", CL_INVALID_VALUE);
     }
@@ -72,16 +72,16 @@ kernel::get_arg_info(cl_uint idx, cl_kernel_arg_info param) const
     switch (param) {
     case CL_KERNEL_ARG_ADDRESS_QUALIFIER:
         return pyopencl_get_int_info(cl_kernel_arg_address_qualifier,
-                                     KernelArg, this, idx, param);
+                                     KernelArg, PYOPENCL_CL_CASTABLE_THIS, idx, param);
     case CL_KERNEL_ARG_ACCESS_QUALIFIER:
         return pyopencl_get_int_info(cl_kernel_arg_access_qualifier,
-                                     KernelArg, this, idx, param);
+                                     KernelArg, PYOPENCL_CL_CASTABLE_THIS, idx, param);
     case CL_KERNEL_ARG_TYPE_QUALIFIER:
         return pyopencl_get_int_info(cl_kernel_arg_type_qualifier,
                                      KernelArg, this, idx, param);
     case CL_KERNEL_ARG_TYPE_NAME:
     case CL_KERNEL_ARG_NAME:
-        return pyopencl_get_str_info(KernelArg, this, idx, param);
+        return pyopencl_get_str_info(KernelArg, PYOPENCL_CL_CASTABLE_THIS, idx, param);
     default:
         throw clerror("Kernel.get_arg_info", CL_INVALID_VALUE);
     }
diff --git a/src/c_wrapper/kernel.h b/src/c_wrapper/kernel.h
index 4a1b332a28fc5537ce4be6c8c3e41c4667593505..5db1a0cc53bcd8171cb6973182d5e82de4ddc479 100644
--- a/src/c_wrapper/kernel.h
+++ b/src/c_wrapper/kernel.h
@@ -21,7 +21,7 @@ public:
         : clobj(knl)
     {
         if (retain) {
-            pyopencl_call_guarded(clRetainKernel, this);
+            pyopencl_call_guarded(clRetainKernel, PYOPENCL_CL_CASTABLE_THIS);
         }
     }
     ~kernel();
diff --git a/src/c_wrapper/memory_map.cpp b/src/c_wrapper/memory_map.cpp
index f9014dcd76462698b7e841cf0eb8fd67f66ea35b..068274df6d6d4c306682ab372b560817d454037a 100644
--- a/src/c_wrapper/memory_map.cpp
+++ b/src/c_wrapper/memory_map.cpp
@@ -14,7 +14,7 @@ memory_map::~memory_map()
     if (!m_valid.exchange(false))
         return;
     pyopencl_call_guarded_cleanup(clEnqueueUnmapMemObject, m_queue,
-                                  m_mem, this, 0, nullptr, nullptr);
+                                  m_mem, PYOPENCL_CL_CASTABLE_THIS, 0, nullptr, nullptr);
 }
 
 void
@@ -28,7 +28,7 @@ memory_map::release(clobj_t *evt, const command_queue *queue,
     const auto wait_for = buf_from_class<event>(_wait_for, num_wait_for);
     queue = queue ? queue : &m_queue;
     pyopencl_call_guarded(clEnqueueUnmapMemObject, queue,
-                          m_mem, this, wait_for, event_out(evt));
+                          m_mem, PYOPENCL_CL_CASTABLE_THIS, wait_for, event_out(evt));
 }
 
 generic_info
diff --git a/src/c_wrapper/memory_object.cpp b/src/c_wrapper/memory_object.cpp
index 98e8fbe56dcb301cc18bc0bc2a2d4cc7ff66596c..de722420a8b01ba6b894128f2f27fe504b9db04f 100644
--- a/src/c_wrapper/memory_object.cpp
+++ b/src/c_wrapper/memory_object.cpp
@@ -15,12 +15,12 @@ memory_object::get_info(cl_uint param_name) const
     switch ((cl_mem_info)param_name) {
     case CL_MEM_TYPE:
         return pyopencl_get_int_info(cl_mem_object_type, MemObject,
-                                     this, param_name);
+                                     PYOPENCL_CL_CASTABLE_THIS, param_name);
     case CL_MEM_FLAGS:
         return pyopencl_get_int_info(cl_mem_flags, MemObject,
-                                     this, param_name);
+                                     PYOPENCL_CL_CASTABLE_THIS, param_name);
     case CL_MEM_SIZE:
-        return pyopencl_get_int_info(size_t, MemObject, this, param_name);
+        return pyopencl_get_int_info(size_t, MemObject, PYOPENCL_CL_CASTABLE_THIS, param_name);
     case CL_MEM_HOST_PTR:
         throw clerror("MemoryObject.get_info", CL_INVALID_VALUE,
                       "Use MemoryObject.get_host_array to get "
@@ -28,9 +28,9 @@ memory_object::get_info(cl_uint param_name) const
     case CL_MEM_MAP_COUNT:
     case CL_MEM_REFERENCE_COUNT:
         return pyopencl_get_int_info(cl_uint, MemObject,
-                                     this, param_name);
+                                     PYOPENCL_CL_CASTABLE_THIS, param_name);
     case CL_MEM_CONTEXT:
-        return pyopencl_get_opaque_info(context, MemObject, this, param_name);
+        return pyopencl_get_opaque_info(context, MemObject, PYOPENCL_CL_CASTABLE_THIS, param_name);
 
 #if PYOPENCL_CL_VERSION >= 0x1010
         // TODO
@@ -47,7 +47,7 @@ memory_object::get_info(cl_uint param_name) const
         //        return create_mem_object_wrapper(param_value);
         //      }
     case CL_MEM_OFFSET:
-        return pyopencl_get_int_info(size_t, MemObject, this, param_name);
+        return pyopencl_get_int_info(size_t, MemObject, PYOPENCL_CL_CASTABLE_THIS, param_name);
 #endif
 #if PYOPENCL_CL_VERSION >= 0x2000
     case CL_MEM_USES_SVM_POINTER:
@@ -63,7 +63,7 @@ memory_object::~memory_object()
 {
     if (!m_valid.exchange(false))
         return;
-    pyopencl_call_guarded_cleanup(clReleaseMemObject, this);
+    pyopencl_call_guarded_cleanup(clReleaseMemObject, PYOPENCL_CL_CASTABLE_THIS);
 }
 
 // c wrapper
diff --git a/src/c_wrapper/memory_object.h b/src/c_wrapper/memory_object.h
index a56972e15f31fc53ecc1b869839628a052f8f911..635dc470ef1966d672799e7099d8452d52a56551 100644
--- a/src/c_wrapper/memory_object.h
+++ b/src/c_wrapper/memory_object.h
@@ -21,7 +21,7 @@ public:
         : clobj(mem), m_valid(true)
     {
         if (retain) {
-            pyopencl_call_guarded(clRetainMemObject, this);
+            pyopencl_call_guarded(clRetainMemObject, PYOPENCL_CL_CASTABLE_THIS);
         }
     }
     PYOPENCL_INLINE
@@ -37,7 +37,7 @@ public:
             throw clerror("MemoryObject.release", CL_INVALID_VALUE,
                           "trying to double-unref mem object");
         }
-        pyopencl_call_guarded(clReleaseMemObject, this);
+        pyopencl_call_guarded(clReleaseMemObject, PYOPENCL_CL_CASTABLE_THIS);
     }
 #if 0
     PYOPENCL_USE_RESULT size_t
diff --git a/src/c_wrapper/platform.cpp b/src/c_wrapper/platform.cpp
index f75f4049b8caa145911f4c6347ffb848c62258a4..13b890f1f8381c038afd18cbd9ca3df9f0616c79 100644
--- a/src/c_wrapper/platform.cpp
+++ b/src/c_wrapper/platform.cpp
@@ -22,7 +22,7 @@ platform::get_info(cl_uint param_name) const
 #if !(defined(CL_PLATFORM_NVIDIA) && CL_PLATFORM_NVIDIA == 0x3001)
     case CL_PLATFORM_EXTENSIONS:
 #endif
-        return pyopencl_get_str_info(Platform, this, param_name);
+        return pyopencl_get_str_info(Platform, PYOPENCL_CL_CASTABLE_THIS, param_name);
     default:
         throw clerror("Platform.get_info", CL_INVALID_VALUE);
     }
diff --git a/src/c_wrapper/program.cpp b/src/c_wrapper/program.cpp
index 6aac02f1d32773c9b45dde582fa77c0db60205b6..39bf829b2ca3041ae1a2055b5461f5e171734afd 100644
--- a/src/c_wrapper/program.cpp
+++ b/src/c_wrapper/program.cpp
@@ -18,7 +18,7 @@ new_program(cl_program prog, program_kind_type progkind=KND_UNKNOWN)
 
 program::~program()
 {
-    pyopencl_call_guarded_cleanup(clReleaseProgram, this);
+    pyopencl_call_guarded_cleanup(clReleaseProgram, PYOPENCL_CL_CASTABLE_THIS);
 }
 
 generic_info
@@ -26,25 +26,25 @@ program::get_info(cl_uint param) const
 {
     switch ((cl_program_info)param) {
     case CL_PROGRAM_CONTEXT:
-        return pyopencl_get_opaque_info(context, Program, this, param);
+        return pyopencl_get_opaque_info(context, Program, PYOPENCL_CL_CASTABLE_THIS, param);
     case CL_PROGRAM_REFERENCE_COUNT:
     case CL_PROGRAM_NUM_DEVICES:
-        return pyopencl_get_int_info(cl_uint, Program, this, param);
+        return pyopencl_get_int_info(cl_uint, Program, PYOPENCL_CL_CASTABLE_THIS, param);
     case CL_PROGRAM_DEVICES:
-        return pyopencl_get_opaque_array_info(device, Program, this, param);
+        return pyopencl_get_opaque_array_info(device, Program, PYOPENCL_CL_CASTABLE_THIS, param);
     case CL_PROGRAM_SOURCE:
-        return pyopencl_get_str_info(Program, this, param);
+        return pyopencl_get_str_info(Program, PYOPENCL_CL_CASTABLE_THIS, param);
     case CL_PROGRAM_BINARY_SIZES:
-        return pyopencl_get_array_info(size_t, Program, this, param);
+        return pyopencl_get_array_info(size_t, Program, PYOPENCL_CL_CASTABLE_THIS, param);
     case CL_PROGRAM_BINARIES: {
-        auto sizes = pyopencl_get_vec_info(size_t, Program, this,
+        auto sizes = pyopencl_get_vec_info(size_t, Program, PYOPENCL_CL_CASTABLE_THIS,
                                            CL_PROGRAM_BINARY_SIZES);
         pyopencl_buf<char*> result_ptrs(sizes.len());
         for (size_t i  = 0;i < sizes.len();i++) {
             result_ptrs[i] = (char*)malloc(sizes[i]);
         }
         try {
-            pyopencl_call_guarded(clGetProgramInfo, this, CL_PROGRAM_BINARIES,
+            pyopencl_call_guarded(clGetProgramInfo, PYOPENCL_CL_CASTABLE_THIS, CL_PROGRAM_BINARIES,
                                   sizes.len() * sizeof(char*),
                                   result_ptrs.get(), nullptr);
         } catch (...) {
@@ -65,9 +65,9 @@ program::get_info(cl_uint param) const
 
 #if PYOPENCL_CL_VERSION >= 0x1020
     case CL_PROGRAM_NUM_KERNELS:
-        return pyopencl_get_int_info(size_t, Program, this, param);
+        return pyopencl_get_int_info(size_t, Program, PYOPENCL_CL_CASTABLE_THIS, param);
     case CL_PROGRAM_KERNEL_NAMES:
-        return pyopencl_get_str_info(Program, this, param);
+        return pyopencl_get_str_info(Program, PYOPENCL_CL_CASTABLE_THIS, param);
 #endif
     default:
         throw clerror("Program.get_info", CL_INVALID_VALUE);
@@ -80,14 +80,14 @@ program::get_build_info(const device *dev, cl_program_build_info param) const
     switch (param) {
     case CL_PROGRAM_BUILD_STATUS:
         return pyopencl_get_int_info(cl_build_status, ProgramBuild,
-                                     this, dev, param);
+                                     PYOPENCL_CL_CASTABLE_THIS, dev, param);
     case CL_PROGRAM_BUILD_OPTIONS:
     case CL_PROGRAM_BUILD_LOG:
-        return pyopencl_get_str_info(ProgramBuild, this, dev, param);
+        return pyopencl_get_str_info(ProgramBuild, PYOPENCL_CL_CASTABLE_THIS, dev, param);
 #if PYOPENCL_CL_VERSION >= 0x1020
     case CL_PROGRAM_BINARY_TYPE:
         return pyopencl_get_int_info(cl_program_binary_type, ProgramBuild,
-                                     this, dev, param);
+                                     PYOPENCL_CL_CASTABLE_THIS, dev, param);
 #endif
 #if PYOPENCL_CL_VERSION >= 0x2000
     case CL_PROGRAM_BUILD_GLOBAL_VARIABLE_TOTAL_SIZE:
@@ -107,7 +107,7 @@ program::compile(const char *opts, const clobj_t *_devs, size_t num_devs,
 {
     const auto devs = buf_from_class<device>(_devs, num_devs);
     const auto prgs = buf_from_class<program>(_prgs, num_hdrs);
-    pyopencl_call_guarded(clCompileProgram, this, devs, opts, prgs,
+    pyopencl_call_guarded(clCompileProgram, PYOPENCL_CL_CASTABLE_THIS, devs, opts, prgs,
                           buf_arg(names, num_hdrs), nullptr, nullptr);
 }
 #endif
@@ -116,10 +116,10 @@ pyopencl_buf<clobj_t>
 program::all_kernels()
 {
     cl_uint num_knls;
-    pyopencl_call_guarded(clCreateKernelsInProgram, this, 0, nullptr,
+    pyopencl_call_guarded(clCreateKernelsInProgram, PYOPENCL_CL_CASTABLE_THIS, 0, nullptr,
                           buf_arg(num_knls));
     pyopencl_buf<cl_kernel> knls(num_knls);
-    pyopencl_call_guarded(clCreateKernelsInProgram, this, knls,
+    pyopencl_call_guarded(clCreateKernelsInProgram, PYOPENCL_CL_CASTABLE_THIS, knls,
                           buf_arg(num_knls));
     return buf_to_base<kernel>(knls, true);
 }
diff --git a/src/c_wrapper/program.h b/src/c_wrapper/program.h
index eef07c12b9f90ec04287f9ff46f4b60235782f00..63d2fc760141bec68a8a1347e5300cb07ccda41b 100644
--- a/src/c_wrapper/program.h
+++ b/src/c_wrapper/program.h
@@ -25,7 +25,7 @@ public:
         : clobj(prog), m_program_kind(progkind)
     {
         if (retain) {
-            pyopencl_call_guarded(clRetainProgram, this);
+            pyopencl_call_guarded(clRetainProgram, PYOPENCL_CL_CASTABLE_THIS);
         }
     }
     ~program();
@@ -37,7 +37,7 @@ public:
     PYOPENCL_USE_RESULT pyopencl_buf<cl_device_id>
     get_info__devices() const
     {
-        return pyopencl_get_vec_info(cl_device_id, Program, this,
+        return pyopencl_get_vec_info(cl_device_id, Program, PYOPENCL_CL_CASTABLE_THIS,
                                      CL_PROGRAM_DEVICES);
     }
     generic_info get_info(cl_uint param_name) const;
diff --git a/src/c_wrapper/sampler.cpp b/src/c_wrapper/sampler.cpp
index ee2e90cfa9ac39fcb9e98932c3287cf8b71aa255..b373c7830f9b1398a7d904b3c153db6b7ad2ab6a 100644
--- a/src/c_wrapper/sampler.cpp
+++ b/src/c_wrapper/sampler.cpp
@@ -10,7 +10,7 @@ template void print_buf<cl_sampler>(std::ostream&, const cl_sampler*,
 
 sampler::~sampler()
 {
-    pyopencl_call_guarded_cleanup(clReleaseSampler, this);
+    pyopencl_call_guarded_cleanup(clReleaseSampler, PYOPENCL_CL_CASTABLE_THIS);
 }
 
 generic_info
@@ -18,16 +18,16 @@ sampler::get_info(cl_uint param_name) const
 {
     switch ((cl_sampler_info)param_name) {
     case CL_SAMPLER_REFERENCE_COUNT:
-        return pyopencl_get_int_info(cl_uint, Sampler, this, param_name);
+        return pyopencl_get_int_info(cl_uint, Sampler, PYOPENCL_CL_CASTABLE_THIS, param_name);
     case CL_SAMPLER_CONTEXT:
-        return pyopencl_get_opaque_info(context, Sampler, this, param_name);
+        return pyopencl_get_opaque_info(context, Sampler, PYOPENCL_CL_CASTABLE_THIS, param_name);
     case CL_SAMPLER_ADDRESSING_MODE:
         return pyopencl_get_int_info(cl_addressing_mode, Sampler,
-                                     this, param_name);
+                                     PYOPENCL_CL_CASTABLE_THIS, param_name);
     case CL_SAMPLER_FILTER_MODE:
-        return pyopencl_get_int_info(cl_filter_mode, Sampler, this, param_name);
+        return pyopencl_get_int_info(cl_filter_mode, Sampler, PYOPENCL_CL_CASTABLE_THIS, param_name);
     case CL_SAMPLER_NORMALIZED_COORDS:
-        return pyopencl_get_int_info(cl_bool, Sampler, this, param_name);
+        return pyopencl_get_int_info(cl_bool, Sampler, PYOPENCL_CL_CASTABLE_THIS, param_name);
 
 #if PYOPENCL_CL_VERSION >= 0x2000
     // TODO: MIP_FILTER_MODE, LOD_MIN, LOD_MAX
diff --git a/src/c_wrapper/sampler.h b/src/c_wrapper/sampler.h
index 0f41eaac563dbfb51fbf9f71063338c34610845f..404b82e57e552393dd2e2b005e54b491584ccd3e 100644
--- a/src/c_wrapper/sampler.h
+++ b/src/c_wrapper/sampler.h
@@ -19,7 +19,7 @@ public:
         : clobj(samp)
     {
         if (retain) {
-            pyopencl_call_guarded(clRetainSampler, this);
+            pyopencl_call_guarded(clRetainSampler, PYOPENCL_CL_CASTABLE_THIS);
         }
     }
     ~sampler();