diff --git a/pyopencl/cffi_cl.py b/pyopencl/cffi_cl.py
index 2851b02cae35d8592bba1ca6589cbac35ee488b4..62f9edbfa2e903cd8143a388f63832692e18314f 100644
--- a/pyopencl/cffi_cl.py
+++ b/pyopencl/cffi_cl.py
@@ -144,6 +144,10 @@ class _CArray(object):
 
 def _generic_info_to_python(info):
     type_ = _ffi_pystr(info.type)
+
+    if info.free_type:
+        _lib.free_pointer(info.type)
+
     value = _ffi.cast(type_, info.value)
 
     if info.opaque_class != _lib.CLASS_NONE:
@@ -200,7 +204,7 @@ def _generic_info_to_python(info):
             ret = list(value)
     else:
         ret = value[0]
-    if info.dontfree == 0:
+    if info.free_value:
         _lib.free_pointer(info.value)
     return ret
 
diff --git a/src/c_wrapper/clhelper.h b/src/c_wrapper/clhelper.h
index c88c00519b899f134a74066e2c9fa9cff547fee7..d0aff85c329ead7956ed2621fa4c00a1c887ab7c 100644
--- a/src/c_wrapper/clhelper.h
+++ b/src/c_wrapper/clhelper.h
@@ -86,17 +86,27 @@ get_vec_info(cl_int (CL_API_CALL *func)(ArgTypes...), const char *name,
 #define pyopencl_get_vec_info(type, what, ...)                      \
     get_vec_info<type>(clGet##what##Info, "clGet" #what "Info", __VA_ARGS__)
 
+inline generic_info make_generic_info(class_t opaque_class, const char *type, bool free_type, void *value, bool free_value)
+{
+  generic_info result;
+  result.opaque_class = opaque_class;
+  result.type = type;
+  result.free_type = free_type;
+  result.value = value;
+  result.free_value = free_value;
+  return result;
+}
+
 template<typename T>
 PYOPENCL_USE_RESULT static PYOPENCL_INLINE generic_info
 convert_array_info(const char *tname, pyopencl_buf<T> &buf)
 {
-    generic_info info;
-    info.dontfree = 0;
-    info.opaque_class = CLASS_NONE;
-    info.type = _copy_str(std::string(tname) + "[" +
-                          tostring(buf.len()) + "]");
-    info.value = buf.release();
-    return info;
+    return make_generic_info(
+        CLASS_NONE,
+        _copy_str(std::string(tname) + "[" + tostring(buf.len()) + "]"),
+        true,
+        buf.release(),
+        true);
 }
 
 template<typename T>
@@ -116,12 +126,12 @@ template<typename CLObj, typename T>
 PYOPENCL_USE_RESULT static PYOPENCL_INLINE generic_info
 convert_opaque_array_info(T &&buf)
 {
-    generic_info info;
-    info.dontfree = 0;
-    info.opaque_class = CLObj::class_id;
-    info.type = _copy_str(std::string("void*[") + tostring(buf.len()) + "]");
-    info.value = buf_to_base<CLObj>(std::forward<T>(buf)).release();
-    return info;
+    return make_generic_info(
+        CLObj::class_id,
+        _copy_str(std::string("void*[") + tostring(buf.len()) + "]"),
+        true,
+        buf_to_base<CLObj>(std::forward<T>(buf)).release(),
+        true);
 }
 #define pyopencl_get_opaque_array_info(cls, what, ...)  \
     convert_opaque_array_info<cls>(               \
@@ -134,16 +144,13 @@ get_opaque_info(cl_int (CL_API_CALL *func)(ArgTypes...), const char *name,
 {
     typename CLObj::cl_type param_value;
     call_guarded(func, name, args..., size_arg(param_value), nullptr);
-    generic_info info;
-    info.dontfree = 0;
-    info.opaque_class = CLObj::class_id;
-    info.type = "void *";
+    void *value;
     if (param_value) {
-        info.value = (void*)(new CLObj(param_value, /*retain*/ true));
+        value = (void*)(new CLObj(param_value, /*retain*/ true));
     } else {
-        info.value = nullptr;
+        value = nullptr;
     }
-    return info;
+    return make_generic_info(CLObj::class_id, "void *", false, value, true);
 }
 #define pyopencl_get_opaque_info(clobj, what, ...)              \
     get_opaque_info<clobj>(clGet##what##Info,             \
@@ -158,12 +165,7 @@ get_str_info(cl_int (CL_API_CALL *func)(ArgTypes...), const char *name,
     call_guarded(func, name, args..., 0, nullptr, buf_arg(size));
     pyopencl_buf<char> param_value(size);
     call_guarded(func, name, args..., param_value, buf_arg(size));
-    generic_info info;
-    info.dontfree = 0;
-    info.opaque_class = CLASS_NONE;
-    info.type = "char*";
-    info.value = (void*)param_value.release();
-    return info;
+    return make_generic_info(CLASS_NONE, "char*", false, (void*)param_value.release(), true);
 }
 #define pyopencl_get_str_info(what, ...)                            \
     get_str_info(clGet##what##Info, "clGet" #what "Info", __VA_ARGS__)
@@ -175,12 +177,7 @@ get_int_info(cl_int (CL_API_CALL *func)(ArgTypes...), const char *name,
 {
     T value;
     call_guarded(func, name, args..., size_arg(value), nullptr);
-    generic_info info;
-    info.dontfree = 0;
-    info.opaque_class = CLASS_NONE;
-    info.type = tpname;
-    info.value = cl_memdup(&value);
-    return info;
+    return make_generic_info(CLASS_NONE, tpname, false, cl_memdup(&value), true);
 }
 #define pyopencl_get_int_info(type, what, ...)                      \
     get_int_info<type>(clGet##what##Info, "clGet" #what "Info", \
diff --git a/src/c_wrapper/context.cpp b/src/c_wrapper/context.cpp
index f2478fd73a54c11dbed830f6eace3e57f9ace215..0fe48554f954e46dad0ef5561932a9cb9fdb75ff 100644
--- a/src/c_wrapper/context.cpp
+++ b/src/c_wrapper/context.cpp
@@ -56,15 +56,12 @@ context::get_info(cl_uint param_name) const
             if (key == 0)
                 break;
             cl_context_properties value = result[i * 2 + 1];
-            generic_info &info = py_result[i];
-            info.dontfree = 0;
-            info.opaque_class = CLASS_NONE;
             switch (key) {
             case CL_CONTEXT_PLATFORM:
-                info.opaque_class = CLASS_PLATFORM;
-                info.type = "void *";
-                info.value = new platform(
-                    reinterpret_cast<cl_platform_id>(value));
+              py_result[i] = make_generic_info(
+                  CLASS_PLATFORM,
+                  "void *", false,
+                  new platform(reinterpret_cast<cl_platform_id>(value)), true);
                 break;
 
 #if defined(PYOPENCL_GL_SHARING_VERSION) && (PYOPENCL_GL_SHARING_VERSION >= 1)
@@ -77,12 +74,13 @@ context::get_info(cl_uint param_name) const
             case CL_WGL_HDC_KHR:
             case CL_CGL_SHAREGROUP_KHR:
 #endif
-                info.type = "intptr_t *";
-                info.value = (void*)value;
-                // we do not own this object
-                info.dontfree = 1;
-                break;
-
+              py_result[i] = make_generic_info(
+                  CLASS_NONE,
+                  "intptr_t *", false,
+                  (void*)value,
+                  // we do not own this object
+                  false);
+              break;
 #endif
             default:
                 throw clerror("Context.get_info", CL_INVALID_VALUE,
diff --git a/src/c_wrapper/device.cpp b/src/c_wrapper/device.cpp
index 7bc7fd5a690b6a092bce17f5b28f15cb436a5c49..16edaf34c7be2934e6350855a1788bf1311a6641 100644
--- a/src/c_wrapper/device.cpp
+++ b/src/c_wrapper/device.cpp
@@ -37,12 +37,7 @@ get_device_topology_amd(ArgTypes&&... args)
     cl_device_topology_amd value;
     const char * fname = "clGetDeviceInfo";
     call_guarded(clGetDeviceInfo, fname, args..., size_arg(value), nullptr);
-    generic_info info;
-    info.dontfree = 0;
-    info.opaque_class = CLASS_NONE;
-    info.type = tpname;
-    info.value = cl_memdup(&value);
-    return info;
+    return make_generic_info(CLASS_NONE, tpname, false, cl_memdup(&value), true);
 }
 
 #define pyopencl_get_device_topology_amd(...) get_device_topology_amd(__VA_ARGS__)
diff --git a/src/c_wrapper/program.cpp b/src/c_wrapper/program.cpp
index d50d96802830269c0b8e35bbda4b85fe97e644c7..a0535c06a9d33abdf4cb91d93a87d6141bd7407a 100644
--- a/src/c_wrapper/program.cpp
+++ b/src/c_wrapper/program.cpp
@@ -54,11 +54,12 @@ program::get_info(cl_uint param) const
         }
         pyopencl_buf<generic_info> gis(sizes.len());
         for (size_t i  = 0;i < sizes.len();i++) {
-            gis[i].value = result_ptrs[i];
-            gis[i].dontfree = 0;
-            gis[i].opaque_class = CLASS_NONE;
-            gis[i].type =  _copy_str(std::string("char[") +
-                                     tostring(sizes[i]) + "]");
+            gis[i] = make_generic_info(
+                CLASS_NONE,
+                _copy_str(std::string("char[") + tostring(sizes[i]) + "]"),
+                true,
+                result_ptrs[i],
+                true);
         }
         return pyopencl_convert_array_info(generic_info, gis);
     }
diff --git a/src/c_wrapper/wrap_cl_core.h b/src/c_wrapper/wrap_cl_core.h
index 746c1b9d85659564a50fdbfdc1890d75d678073d..184cd001f5157661aa0a70732e06fc327694c32b 100644
--- a/src/c_wrapper/wrap_cl_core.h
+++ b/src/c_wrapper/wrap_cl_core.h
@@ -43,8 +43,9 @@ typedef enum {
 typedef struct {
     class_t opaque_class;
     const char *type;
+    bool free_type;
     void *value;
-    int dontfree;
+    bool free_value;
 } generic_info;
 
 // }}}