diff --git a/pyopencl/cffi_cl.py b/pyopencl/cffi_cl.py
index 2b659bdedd38b16372434078fae08e356f46afa1..096ebf796338932adfb0a9bfb0f8ac8def25c283 100644
--- a/pyopencl/cffi_cl.py
+++ b/pyopencl/cffi_cl.py
@@ -230,10 +230,18 @@ class _Common(object):
         return _lib.clobj__int_ptr(self.ptr)
 
     @classmethod
-    def from_int_ptr(cls, int_ptr_value):
+    def from_int_ptr(cls, int_ptr_value, retain=True):
+        """Constructs a :mod:`pyopencl` handle from a C-level pointer (given as
+        the integer *int_ptr_value*). If *retain* is *True* (the defauult)
+        :mod:`pyopencl` will call ``clRetainXXX`` on the provided object. If
+        the previous owner of the object will *not* release the reference,
+        *retain* should be set to *False*, to effectively transfer ownership to
+        :mod:`pyopencl`.
+        """
         ptr = _ffi.new('clobj_t*')
         _handle_error(_lib.clobj__from_int_ptr(
-            ptr, int_ptr_value, getattr(_lib, 'CLASS_%s' % cls._id.upper())))
+            ptr, int_ptr_value, getattr(_lib, 'CLASS_%s' % cls._id.upper()),
+            retain))
         return cls._create(ptr[0])
 
 # }}}
diff --git a/src/c_wrapper/clobj.h b/src/c_wrapper/clobj.h
index 6d2982282c6aa5c26642d2ea8475e0b86a1855fc..5db08710f2b10193b5cc5e8528257317f666de32 100644
--- a/src/c_wrapper/clobj.h
+++ b/src/c_wrapper/clobj.h
@@ -94,9 +94,9 @@ public:
 
 template<typename CLObj>
 static PYOPENCL_INLINE CLObj*
-clobj_from_int_ptr(intptr_t ptr)
+clobj_from_int_ptr(intptr_t ptr, bool retain)
 {
-    return new CLObj(reinterpret_cast<typename CLObj::cl_type>(ptr), true);
+    return new CLObj(reinterpret_cast<typename CLObj::cl_type>(ptr), retain);
 }
 
 template<typename T, typename T2>
diff --git a/src/c_wrapper/wrap_cl.cpp b/src/c_wrapper/wrap_cl.cpp
index 5a88c05ea38c6dff6411b204d66403f17ef0d030..1e001eb4eeb938f0b8d3656672084889095b6990 100644
--- a/src/c_wrapper/wrap_cl.cpp
+++ b/src/c_wrapper/wrap_cl.cpp
@@ -59,34 +59,34 @@ clobj__int_ptr(clobj_t obj)
 }
 
 static PYOPENCL_INLINE clobj_t
-_from_int_ptr(intptr_t ptr, class_t class_)
+_from_int_ptr(intptr_t ptr, class_t class_, bool retain)
 {
     switch(class_) {
     case CLASS_PLATFORM:
-        return clobj_from_int_ptr<platform>(ptr);
+        return clobj_from_int_ptr<platform>(ptr, retain);
     case CLASS_DEVICE:
-        return clobj_from_int_ptr<device>(ptr);
+        return clobj_from_int_ptr<device>(ptr, retain);
     case CLASS_KERNEL:
-        return clobj_from_int_ptr<kernel>(ptr);
+        return clobj_from_int_ptr<kernel>(ptr, retain);
     case CLASS_CONTEXT:
-        return clobj_from_int_ptr<context>(ptr);
+        return clobj_from_int_ptr<context>(ptr, retain);
     case CLASS_COMMAND_QUEUE:
-        return clobj_from_int_ptr<command_queue>(ptr);
+        return clobj_from_int_ptr<command_queue>(ptr, retain);
     case CLASS_BUFFER:
-        return clobj_from_int_ptr<buffer>(ptr);
+        return clobj_from_int_ptr<buffer>(ptr, retain);
     case CLASS_PROGRAM:
-        return clobj_from_int_ptr<program>(ptr);
+        return clobj_from_int_ptr<program>(ptr, retain);
     case CLASS_EVENT:
-        return clobj_from_int_ptr<event>(ptr);
+        return clobj_from_int_ptr<event>(ptr, retain);
     case CLASS_IMAGE:
-        return clobj_from_int_ptr<image>(ptr);
+        return clobj_from_int_ptr<image>(ptr, retain);
     case CLASS_SAMPLER:
-        return clobj_from_int_ptr<sampler>(ptr);
+        return clobj_from_int_ptr<sampler>(ptr, retain);
 #ifdef HAVE_GL
     case CLASS_GL_BUFFER:
-        return clobj_from_int_ptr<gl_buffer>(ptr);
+        return clobj_from_int_ptr<gl_buffer>(ptr, retain);
     case CLASS_GL_RENDERBUFFER:
-        return clobj_from_int_ptr<gl_renderbuffer>(ptr);
+        return clobj_from_int_ptr<gl_renderbuffer>(ptr, retain);
 #endif
     default:
         throw clerror("unknown class", CL_INVALID_VALUE);
@@ -94,10 +94,10 @@ _from_int_ptr(intptr_t ptr, class_t class_)
 }
 
 error*
-clobj__from_int_ptr(clobj_t *out, intptr_t ptr, class_t class_)
+clobj__from_int_ptr(clobj_t *out, intptr_t ptr, class_t class_, int retain)
 {
     return c_handle_error([&] {
-            *out = _from_int_ptr(ptr, class_);
+            *out = _from_int_ptr(ptr, class_, retain);
         });
 }
 
diff --git a/src/c_wrapper/wrap_cl_core.h b/src/c_wrapper/wrap_cl_core.h
index 606ff40fdb2ebfa11d8a030f0ef987d9ac1cb4b0..7a5eefa4a690ce4c5126a490b690c6cdc0612cea 100644
--- a/src/c_wrapper/wrap_cl_core.h
+++ b/src/c_wrapper/wrap_cl_core.h
@@ -290,4 +290,4 @@ error *enqueue_copy_buffer_to_image(clobj_t *evt, clobj_t _queue, clobj_t _src,
 intptr_t clobj__int_ptr(clobj_t obj);
 error *clobj__get_info(clobj_t obj, cl_uint param, generic_info *out);
 void clobj__delete(clobj_t obj);
-error *clobj__from_int_ptr(clobj_t *out, intptr_t ptr, class_t);
+error *clobj__from_int_ptr(clobj_t *out, intptr_t ptr, class_t, int);