diff --git a/pyopencl/__init__.py b/pyopencl/__init__.py
index c99434bd4e7954d64134d59a8a9c24268bcb481b..4a81e306177995b98ab7d8a34f2974164540299e 100644
--- a/pyopencl/__init__.py
+++ b/pyopencl/__init__.py
@@ -356,8 +356,8 @@ class Program(object):
         return self._get_prg().int_ptr
     int_ptr = property(int_ptr, doc=_cl._Program.int_ptr.__doc__)
 
-    def from_int_ptr(int_ptr_value):
-        return Program(_cl._Program.from_int_ptr(int_ptr_value))
+    def from_int_ptr(int_ptr_value, retain=true):
+        return Program(_cl._Program.from_int_ptr(int_ptr_value), retain)
     from_int_ptr.__doc__ = _cl._Program.from_int_ptr.__doc__
     from_int_ptr = staticmethod(from_int_ptr)
 
diff --git a/src/wrap_cl.hpp b/src/wrap_cl.hpp
index 8d8a8d187a194976b134e6cde10cc91433d80649..ba6a754458c2effd22d7b553d9e482b9c6a67673 100644
--- a/src/wrap_cl.hpp
+++ b/src/wrap_cl.hpp
@@ -1775,7 +1775,7 @@ namespace pyopencl
 
   // {{{ memory_object
 
-  py::object create_mem_object_wrapper(cl_mem mem);
+  py::object create_mem_object_wrapper(cl_mem mem, bool retain);
 
   class memory_object_holder
   {
@@ -2480,7 +2480,7 @@ namespace pyopencl
                 return py::none();
               }
 
-              return create_mem_object_wrapper(param_value);
+              return create_mem_object_wrapper(param_value, /* retain */ true);
             }
 
           case CL_IMAGE_NUM_MIP_LEVELS:
@@ -4688,7 +4688,7 @@ namespace pyopencl
 
   // {{{ deferred implementation bits
 
-  inline py::object create_mem_object_wrapper(cl_mem mem)
+  inline py::object create_mem_object_wrapper(cl_mem mem, bool retain=true)
   {
     cl_mem_object_type mem_obj_type;
     PYOPENCL_CALL_GUARDED(clGetMemObjectInfo, \
@@ -4698,7 +4698,7 @@ namespace pyopencl
     {
       case CL_MEM_OBJECT_BUFFER:
         return py::object(handle_from_new_ptr(
-              new buffer(mem, /*retain*/ true)));
+              new buffer(mem, retain)));
       case CL_MEM_OBJECT_IMAGE2D:
       case CL_MEM_OBJECT_IMAGE3D:
 #if PYOPENCL_CL_VERSION >= 0x1020
@@ -4708,17 +4708,17 @@ namespace pyopencl
       case CL_MEM_OBJECT_IMAGE1D_BUFFER:
 #endif
         return py::object(handle_from_new_ptr(
-              new image(mem, /*retain*/ true)));
+              new image(mem, retain)));
       default:
         return py::object(handle_from_new_ptr(
-              new memory_object(mem, /*retain*/ true)));
+              new memory_object(mem, retain)));
     }
   }
 
   inline
-  py::object memory_object_from_int(intptr_t cl_mem_as_int)
+  py::object memory_object_from_int(intptr_t cl_mem_as_int, bool retain)
   {
-    return create_mem_object_wrapper((cl_mem) cl_mem_as_int);
+    return create_mem_object_wrapper((cl_mem) cl_mem_as_int, retain);
   }
 
 
diff --git a/src/wrap_cl_part_1.cpp b/src/wrap_cl_part_1.cpp
index 6309f98a5916f8d5a5f53aed39d032a5dc2dc8a5..e102a560922b5abde5376b05073430bc6c2d3a67 100644
--- a/src/wrap_cl_part_1.cpp
+++ b/src/wrap_cl_part_1.cpp
@@ -187,11 +187,17 @@ void pyopencl_expose_part_1(py::module &m)
       .def_property_readonly("hostbuf", &cls::hostbuf)
 
       .def_static("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") \
+        "(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 if *retain* is True."
+        "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`."
+        "\n\n.. versionadded:: 2013.2\n",
+        "\n\n.. versionchanged:: 2016.1\n\n    *retain* added.",
+        py::arg("int_ptr_value"),
+        py::arg("retain")=true)
       ;
   }
 
diff --git a/src/wrap_helpers.hpp b/src/wrap_helpers.hpp
index d9b2389dbb32f5121bca8af8da5c56292bb3efd7..4a2d1ee99e8fd044897e9791680ffc1a5c139222 100644
--- a/src/wrap_helpers.hpp
+++ b/src/wrap_helpers.hpp
@@ -128,10 +128,10 @@ namespace
   }
 
   template <typename T, typename ClType>
-  inline T *from_int_ptr(intptr_t obj_ref)
+  inline T *from_int_ptr(intptr_t obj_ref, bool retain)
   {
     ClType clobj = (ClType) obj_ref;
-    return new T(clobj, /* retain */ true);
+    return new T(clobj, retain);
   }
 
   template <typename T>
@@ -144,11 +144,16 @@ namespace
 #define PYOPENCL_EXPOSE_TO_FROM_INT_PTR(CL_TYPENAME) \
   .def_static("from_int_ptr", from_int_ptr<cls, CL_TYPENAME>, \
       py::arg("int_ptr_value"), \
+      py::arg("retain")=true, \
       "(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") \
+      "will be called if *retain* is True." \
+      "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`." \
+      "\n\n.. versionadded:: 2013.2\n" \
+      "\n\n.. versionchanged:: 2016.1\n\n    *retain* added.") \
   .def_property_readonly("int_ptr", to_int_ptr<cls>, \
       "Return an integer corresponding to the pointer value " \
       "of the underlying :c:type:`" #CL_TYPENAME "`. " \