diff --git a/src/c_wrapper/buffer.cpp b/src/c_wrapper/buffer.cpp
index a4d999dded5334cb21d8741a42a2be8df9ca558d..a9223e8faba698ab6e1ce55596617577f0bc5508 100644
--- a/src/c_wrapper/buffer.cpp
+++ b/src/c_wrapper/buffer.cpp
@@ -5,6 +5,8 @@
 
 namespace pyopencl {
 
+template void print_clobj<buffer>(std::ostream&, const buffer*);
+
 PYOPENCL_USE_RESULT static PYOPENCL_INLINE buffer*
 new_buffer(cl_mem mem)
 {
diff --git a/src/c_wrapper/buffer.h b/src/c_wrapper/buffer.h
index 4681b192337423ce3540a3ec7bcfe4b3f808d431..14b8118fb77e9e46b791ec39ba40ed0c8656a4ca 100644
--- a/src/c_wrapper/buffer.h
+++ b/src/c_wrapper/buffer.h
@@ -22,6 +22,8 @@ public:
 #endif
 };
 
+extern template void print_clobj<buffer>(std::ostream&, const buffer*);
+
 // }}}
 
 }
diff --git a/src/c_wrapper/clhelper.h b/src/c_wrapper/clhelper.h
index 17962280f2a645112cf7259d6eacf9f69738a896..d8e5556bfb53125efcc2888317c6fbf6b6901600 100644
--- a/src/c_wrapper/clhelper.h
+++ b/src/c_wrapper/clhelper.h
@@ -6,6 +6,72 @@
 
 namespace pyopencl {
 
+template<typename CLObj, typename... T>
+class _CLObjOutArg : public OutArg {
+    typedef typename CLObj::cl_type CLType;
+    clobj_t *const m_ret;
+    CLType m_clobj;
+    cl_int (*m_release)(CLType);
+    const char *m_name;
+    std::tuple<T...> m_t1;
+    template<int... S>
+    PYOPENCL_INLINE CLObj*
+    __new_obj(seq<S...>)
+    {
+        return new CLObj(m_clobj, false, std::get<S>(m_t1)...);
+    }
+public:
+    PYOPENCL_INLINE
+    _CLObjOutArg(clobj_t *ret, cl_int (*release)(CLType),
+                 const char *name, T... t1) noexcept
+        : m_ret(ret), m_clobj(nullptr), m_release(release),
+          m_name(name), m_t1(t1...)
+    {
+    }
+    PYOPENCL_INLINE
+    _CLObjOutArg(_CLObjOutArg<CLObj, T...> &&other) noexcept
+        : m_ret(other.m_ret), m_clobj(other.m_clobj),
+          m_release(other.m_release), m_name(other.m_name)
+    {
+        std::swap(m_t1, other.m_t1);
+    }
+    PYOPENCL_INLINE typename CLObj::cl_type*
+    get()
+    {
+        return &m_clobj;
+    }
+    PYOPENCL_INLINE void
+    convert()
+    {
+        *m_ret = __new_obj(typename gens<sizeof...(T)>::type());
+    }
+    PYOPENCL_INLINE void
+    cleanup(bool converted)
+    {
+        if (converted) {
+            delete *m_ret;
+            *m_ret = nullptr;
+        } else {
+            call_guarded_cleanup(m_release, m_name, m_clobj);
+        }
+    }
+    PYOPENCL_INLINE void
+    print(std::ostream &stm, bool out=false) const
+    {
+        print_arg(stm, m_clobj, out);
+    }
+};
+
+template<typename CLObj, typename... T>
+static PYOPENCL_INLINE _CLObjOutArg<CLObj, T...>
+make_cloutarg(clobj_t *ret, cl_int (*release)(typename CLObj::cl_type),
+              const char *name, T... t1)
+{
+    return _CLObjOutArg<CLObj, T...>(ret, release, name, t1...);
+}
+#define pyopencl_outarg(type, ret, func, args...)               \
+    pyopencl::make_cloutarg<type>(ret, func, #func, ##args)
+
 // {{{ GetInfo helpers
 
 template<typename T, typename... ArgTypes, typename... ArgTypes2>
@@ -141,76 +207,6 @@ convert_obj(cl_int (*clRelease)(CLType), const char *name, CLType cl_obj,
 #define pyopencl_convert_obj(type, func, args...)       \
     pyopencl::convert_obj<type>(func, #func, args)
 
-template<typename CLObj, typename... T>
-class _CLObjOutArg : public OutArg {
-    typedef typename CLObj::cl_type CLType;
-    clobj_t *const m_ret;
-    CLType m_clobj;
-    cl_int (*m_release)(CLType);
-    const char *m_name;
-    std::tuple<T...> m_t1;
-    template<int... S>
-    PYOPENCL_INLINE CLObj*
-    __new_obj(seq<S...>)
-    {
-        return new CLObj(m_clobj, false, std::get<S>(m_t1)...);
-    }
-public:
-    PYOPENCL_INLINE
-    _CLObjOutArg(clobj_t *ret, cl_int (*release)(CLType),
-                 const char *name, T... t1) noexcept
-        : m_ret(ret), m_clobj(nullptr), m_release(release),
-          m_name(name), m_t1(t1...)
-    {
-    }
-    PYOPENCL_INLINE
-    _CLObjOutArg(_CLObjOutArg<CLObj, T...> &&other) noexcept
-        : m_ret(other.m_ret), m_clobj(other.m_clobj),
-          m_release(other.m_release), m_name(other.m_name)
-    {
-        std::swap(m_t1, other.m_t1);
-    }
-    PYOPENCL_INLINE typename CLObj::cl_type*
-    get()
-    {
-        return &m_clobj;
-    }
-    PYOPENCL_INLINE void
-    convert()
-    {
-        *m_ret = __new_obj(typename gens<sizeof...(T)>::type());
-    }
-    PYOPENCL_INLINE void
-    cleanup(bool converted)
-    {
-        if (converted) {
-            delete *m_ret;
-            *m_ret = nullptr;
-        } else {
-            call_guarded_cleanup(m_release, m_name, m_clobj);
-        }
-    }
-    PYOPENCL_INLINE void
-    print(std::ostream &stm, bool out=false)
-    {
-        if (!out) {
-            stm << &m_clobj;
-        } else {
-            stm << "*(" << &m_clobj << "): " << m_clobj;
-        }
-    }
-};
-
-template<typename CLObj, typename... T>
-static PYOPENCL_INLINE _CLObjOutArg<CLObj, T...>
-make_cloutarg(clobj_t *ret, cl_int (*release)(typename CLObj::cl_type),
-              const char *name, T... t1)
-{
-    return _CLObjOutArg<CLObj, T...>(ret, release, name, t1...);
-}
-#define pyopencl_outarg(type, ret, func, args...)               \
-    pyopencl::make_cloutarg<type>(ret, func, #func, ##args)
-
 // {{{ extension function pointers
 
 #if PYOPENCL_CL_VERSION >= 0x1020
@@ -249,7 +245,7 @@ static PYOPENCL_INLINE std::ostream&
 operator<<(std::ostream &stm, const cl_image_format &fmt)
 {
     stm << "channel_order: " << fmt.image_channel_order
-        << "channel_data_type: " << fmt.image_channel_data_type;
+        << ",\nchannel_data_type: " << fmt.image_channel_data_type;
     return stm;
 }
 
diff --git a/src/c_wrapper/command_queue.cpp b/src/c_wrapper/command_queue.cpp
index 583374a461a0f471936ec27420ed63247ce4d40c..bede3cbf5b092492e91c2bba78bc5439aba6f25d 100644
--- a/src/c_wrapper/command_queue.cpp
+++ b/src/c_wrapper/command_queue.cpp
@@ -7,6 +7,11 @@
 namespace pyopencl {
 
 template class clobj<cl_command_queue>;
+template void print_arg<cl_command_queue>(std::ostream&,
+                                          const cl_command_queue&, bool);
+template void print_clobj<command_queue>(std::ostream&, const command_queue*);
+template void print_buf<cl_command_queue>(
+    std::ostream&, const cl_command_queue*, size_t, ArgType, bool, bool);
 
 command_queue::~command_queue()
 {
diff --git a/src/c_wrapper/command_queue.h b/src/c_wrapper/command_queue.h
index c5970d31e4168acaf475cc3a187b40ac5ac0c05a..ef39845987ec5cb18414192517c21b6e92cde8a5 100644
--- a/src/c_wrapper/command_queue.h
+++ b/src/c_wrapper/command_queue.h
@@ -8,6 +8,10 @@ namespace pyopencl {
 // {{{ command_queue
 
 extern template class clobj<cl_command_queue>;
+extern template void print_arg<cl_command_queue>(
+    std::ostream&, const cl_command_queue&, bool);
+extern template void print_buf<cl_command_queue>(
+    std::ostream&, const cl_command_queue*, size_t, ArgType, bool, bool);
 
 class command_queue : public clobj<cl_command_queue> {
 public:
@@ -54,6 +58,9 @@ public:
 #endif
 };
 
+extern template void print_clobj<command_queue>(std::ostream&,
+                                                const command_queue*);
+
 // }}}
 
 }
diff --git a/src/c_wrapper/context.cpp b/src/c_wrapper/context.cpp
index 628b6c5e09edc328cfef16b3e321b1427c5ca0c9..fd8f485504cd9cfaa7e0d407a796a5f289689bd7 100644
--- a/src/c_wrapper/context.cpp
+++ b/src/c_wrapper/context.cpp
@@ -6,6 +6,10 @@
 namespace pyopencl {
 
 template class clobj<cl_context>;
+template void print_arg<cl_context>(std::ostream&, const cl_context&, bool);
+template void print_clobj<context>(std::ostream&, const context*);
+template void print_buf<cl_context>(std::ostream&, const cl_context*,
+                                    size_t, ArgType, bool, bool);
 
 context::~context()
 {
diff --git a/src/c_wrapper/context.h b/src/c_wrapper/context.h
index 44ffc92ad91ff1bc9983e7eb07334b3d23b6eb00..be18a3fc7df126ccf5844c5283833162238e3808 100644
--- a/src/c_wrapper/context.h
+++ b/src/c_wrapper/context.h
@@ -8,6 +8,10 @@ namespace pyopencl {
 // {{{ context
 
 extern template class clobj<cl_context>;
+extern template void print_arg<cl_context>(std::ostream&,
+                                           const cl_context&, bool);
+extern template void print_buf<cl_context>(std::ostream&, const cl_context*,
+                                           size_t, ArgType, bool, bool);
 
 class context : public clobj<cl_context> {
 public:
@@ -24,6 +28,8 @@ public:
     generic_info get_info(cl_uint param_name) const;
 };
 
+extern template void print_clobj<context>(std::ostream&, const context*);
+
 // }}}
 
 }
diff --git a/src/c_wrapper/device.cpp b/src/c_wrapper/device.cpp
index 54d1b7de4d16b149ea8b992cccdc7a974e3e5f35..1d94bb92b5f4ad9d150ee102785b07597ec18e06 100644
--- a/src/c_wrapper/device.cpp
+++ b/src/c_wrapper/device.cpp
@@ -4,6 +4,11 @@
 namespace pyopencl {
 
 template class clobj<cl_device_id>;
+template void print_arg<cl_device_id>(std::ostream&,
+                                      const cl_device_id&, bool);
+template void print_clobj<device>(std::ostream&, const device*);
+template void print_buf<cl_device_id>(std::ostream&, const cl_device_id*,
+                                      size_t, ArgType, bool, bool);
 
 device::~device()
 {
diff --git a/src/c_wrapper/device.h b/src/c_wrapper/device.h
index 402461eb945d35421713a50cf62c6de132c573a4..1d0d0928534bb9d2c977f12c358816e4628cb240 100644
--- a/src/c_wrapper/device.h
+++ b/src/c_wrapper/device.h
@@ -8,6 +8,10 @@ namespace pyopencl {
 // {{{ device
 
 extern template class clobj<cl_device_id>;
+extern template void print_arg<cl_device_id>(std::ostream&,
+                                             const cl_device_id&, bool);
+extern template void print_buf<cl_device_id>(std::ostream&, const cl_device_id*,
+                                             size_t, ArgType, bool, bool);
 
 class device : public clobj<cl_device_id> {
 public:
@@ -130,6 +134,8 @@ public:
     // #endif
 };
 
+extern template void print_clobj<device>(std::ostream&, const device*);
+
 // }}}
 
 }
diff --git a/src/c_wrapper/error.h b/src/c_wrapper/error.h
index dfcef093d0e7acf4517bdc8911a2124615e46daa..e847a1a068993ff24495ae7fdfdf3c33332cb82e 100644
--- a/src/c_wrapper/error.h
+++ b/src/c_wrapper/error.h
@@ -108,7 +108,7 @@ struct __CLPrintOut {
 template<typename T>
 struct __CLPrintOut<T, typename std::enable_if<
                            std::remove_reference<T>::type::is_out>::type> {
-    static PYOPENCL_INLINE void
+    static inline void
     call(T v, std::ostream &stm)
     {
         v.print(stm, true);
@@ -118,7 +118,7 @@ struct __CLPrintOut<T, typename std::enable_if<
 
 template<typename T, class = void>
 struct __CLPrint {
-    static PYOPENCL_INLINE void
+    static inline void
     call(T v, std::ostream &stm)
     {
         v.print(stm);
@@ -159,9 +159,9 @@ public:
     clcall(Func func, const char *name)
         -> decltype(this->template call<__CLArgGetter>(func))
     {
-        typename CLArgPack::tuple_base *that = this;
         auto res = this->template call<__CLArgGetter>(func);
         if (DEBUG_ON) {
+            typename CLArgPack::tuple_base *that = this;
             std::cerr << name << "(";
             __CLCall<__CLPrint, sizeof...(Types) - 1,
                      decltype(*that)>::call(*that, std::cerr);
@@ -249,7 +249,7 @@ c_handle_error(std::function<void()> func) noexcept
     try {
         func();
         return nullptr;
-    } catch(const clerror &e) {
+    } catch (const clerror &e) {
         auto err = (::error*)malloc(sizeof(::error));
         err->routine = strdup(e.routine());
         err->msg = strdup(e.what());
diff --git a/src/c_wrapper/event.cpp b/src/c_wrapper/event.cpp
index e618937ab491d10f533428406dd25c1e1e482ea6..f9004448336861e0052339d2f17bd1a6023d9dc2 100644
--- a/src/c_wrapper/event.cpp
+++ b/src/c_wrapper/event.cpp
@@ -7,6 +7,10 @@
 namespace pyopencl {
 
 template class clobj<cl_event>;
+template void print_arg<cl_event>(std::ostream&, const cl_event&, bool);
+template void print_clobj<event>(std::ostream&, const event*);
+template void print_buf<cl_event>(std::ostream&, const cl_event*,
+                                  size_t, ArgType, bool, bool);
 
 #if PYOPENCL_CL_VERSION >= 0x1010
 class event_callback {
diff --git a/src/c_wrapper/event.h b/src/c_wrapper/event.h
index 964efe0de6e4c8338a3f0999c0976a76a28e8a34..2160b07cd999128ad998835fdb10ff16bd1071c9 100644
--- a/src/c_wrapper/event.h
+++ b/src/c_wrapper/event.h
@@ -8,6 +8,9 @@ namespace pyopencl {
 // {{{ event
 
 extern template class clobj<cl_event>;
+extern template void print_arg<cl_event>(std::ostream&, const cl_event&, bool);
+extern template void print_buf<cl_event>(std::ostream&, const cl_event*,
+                                         size_t, ArgType, bool, bool);
 
 class event : public clobj<cl_event> {
 public:
@@ -39,6 +42,8 @@ event_out(clobj_t *ret)
     return pyopencl_outarg(event, ret, clReleaseEvent);
 }
 
+extern template void print_clobj<event>(std::ostream&, const event*);
+
 class nanny_event : public event {
 private:
     void *m_ward;
diff --git a/src/c_wrapper/gl_obj.cpp b/src/c_wrapper/gl_obj.cpp
index 690a7ee237287dff6f308cc0426a949cef28427b..7358011b52a0364bd30a756b8ce0e81bd38a0624 100644
--- a/src/c_wrapper/gl_obj.cpp
+++ b/src/c_wrapper/gl_obj.cpp
@@ -8,6 +8,10 @@
 
 namespace pyopencl {
 
+template void print_clobj<gl_buffer>(std::ostream&, const gl_buffer*);
+template void print_clobj<gl_renderbuffer>(std::ostream&,
+                                           const gl_renderbuffer*);
+
 generic_info
 gl_texture::get_gl_texture_info(cl_gl_texture_info param_name) const
 {
diff --git a/src/c_wrapper/gl_obj.h b/src/c_wrapper/gl_obj.h
index 3ff225db70fa4d53679947bd292cd54ab9d018b3..f14637a54da3325e91ae600e98c96c5b310b298b 100644
--- a/src/c_wrapper/gl_obj.h
+++ b/src/c_wrapper/gl_obj.h
@@ -38,6 +38,10 @@ public:
     {}
 };
 
+extern template void print_clobj<gl_buffer>(std::ostream&, const gl_buffer*);
+extern template void print_clobj<gl_renderbuffer>(std::ostream&,
+                                                  const gl_renderbuffer*);
+
 class gl_texture : public image {
   public:
     PYOPENCL_INLINE
diff --git a/src/c_wrapper/image.cpp b/src/c_wrapper/image.cpp
index 986e792c1c4b8dbed7d8cb3436d10859009c8152..b17005820be91f5ddff2e6998a18e8fd9e60cc4d 100644
--- a/src/c_wrapper/image.cpp
+++ b/src/c_wrapper/image.cpp
@@ -5,6 +5,8 @@
 
 namespace pyopencl {
 
+template void print_clobj<image>(std::ostream&, const image*);
+
 PYOPENCL_USE_RESULT static PYOPENCL_INLINE image*
 new_image(cl_mem mem, const cl_image_format *fmt)
 {
diff --git a/src/c_wrapper/image.h b/src/c_wrapper/image.h
index 74faa71dc4da5d3b6e1b7cc2aef39cfac6e671bd..72f062bf8fa1dbec1fa5b95635298caa4aca1513 100644
--- a/src/c_wrapper/image.h
+++ b/src/c_wrapper/image.h
@@ -43,6 +43,8 @@ public:
     }
 };
 
+extern template void print_clobj<image>(std::ostream&, const image*);
+
 // }}}
 
 }
diff --git a/src/c_wrapper/kernel.cpp b/src/c_wrapper/kernel.cpp
index a8dec6049383fe415e7e8ec6c84b90b983c4a803..a4a19d5f319fc1a1f6b63f036a90415ddcabf493 100644
--- a/src/c_wrapper/kernel.cpp
+++ b/src/c_wrapper/kernel.cpp
@@ -11,6 +11,10 @@
 namespace pyopencl {
 
 template class clobj<cl_kernel>;
+template void print_arg<cl_kernel>(std::ostream&, const cl_kernel&, bool);
+template void print_clobj<kernel>(std::ostream&, const kernel*);
+template void print_buf<cl_kernel>(std::ostream&, const cl_kernel*,
+                                   size_t, ArgType, bool, bool);
 
 kernel::~kernel()
 {
diff --git a/src/c_wrapper/kernel.h b/src/c_wrapper/kernel.h
index 5029d0c335c8cb245625195c01f084826a16a278..fda782d048d370560672981abdc7256ea7656c6e 100644
--- a/src/c_wrapper/kernel.h
+++ b/src/c_wrapper/kernel.h
@@ -10,6 +10,10 @@ class device;
 // {{{ kernel
 
 extern template class clobj<cl_kernel>;
+extern template void print_arg<cl_kernel>(std::ostream&,
+                                          const cl_kernel&, bool);
+extern template void print_buf<cl_kernel>(std::ostream&, const cl_kernel*,
+                                          size_t, ArgType, bool, bool);
 
 class kernel : public clobj<cl_kernel> {
 public:
@@ -59,6 +63,8 @@ public:
     // #endif
 };
 
+extern template void print_clobj<kernel>(std::ostream&, const kernel*);
+
 // }}}
 
 }
diff --git a/src/c_wrapper/memory_map.cpp b/src/c_wrapper/memory_map.cpp
index d82b571dfa4e584cf59d7a5ef4f56ee6bc67af4c..3b4c15b50f602f8eb747f71267453072d3b4b405 100644
--- a/src/c_wrapper/memory_map.cpp
+++ b/src/c_wrapper/memory_map.cpp
@@ -7,6 +7,9 @@
 namespace pyopencl {
 
 template class clobj<void*>;
+template void print_arg<void*>(std::ostream&, void *const&, bool);
+template void print_buf<void*>(std::ostream&, void *const*,
+                               size_t, ArgType, bool, bool);
 
 memory_map::~memory_map()
 {
diff --git a/src/c_wrapper/memory_map.h b/src/c_wrapper/memory_map.h
index 714a451dad08432ff8bcf307440dd60b8ab9c43a..8836b374d096133664f5226b749f7e52b757b1df 100644
--- a/src/c_wrapper/memory_map.h
+++ b/src/c_wrapper/memory_map.h
@@ -12,6 +12,9 @@ class event;
 // {{{ memory_map
 
 extern template class clobj<void*>;
+extern template void print_arg<void*>(std::ostream&, void *const&, bool);
+extern template void print_buf<void*>(std::ostream&, void *const*,
+                                      size_t, ArgType, bool, bool);
 
 class memory_map : public clobj<void*> {
 private:
diff --git a/src/c_wrapper/memory_object.cpp b/src/c_wrapper/memory_object.cpp
index b2f0f02d8dcadd933f8763afbc9975cdaf1cfceb..b347e7436c6b2af63f09b96cd67743cdd6447f30 100644
--- a/src/c_wrapper/memory_object.cpp
+++ b/src/c_wrapper/memory_object.cpp
@@ -5,6 +5,9 @@
 namespace pyopencl {
 
 template class clobj<cl_mem>;
+template void print_arg<cl_mem>(std::ostream&, const cl_mem&, bool);
+template void print_buf<cl_mem>(std::ostream&, const cl_mem*,
+                                size_t, ArgType, bool, bool);
 
 generic_info
 memory_object::get_info(cl_uint param_name) const
diff --git a/src/c_wrapper/memory_object.h b/src/c_wrapper/memory_object.h
index 42c60bc157ee8e124c6f0f4d1b35d18afe92ae21..39df1bc7b791b0350db92d5ac393ef0022afbcc1 100644
--- a/src/c_wrapper/memory_object.h
+++ b/src/c_wrapper/memory_object.h
@@ -9,6 +9,9 @@ namespace pyopencl {
 // {{{ memory_object
 
 extern template class clobj<cl_mem>;
+extern template void print_arg<cl_mem>(std::ostream&, const cl_mem&, bool);
+extern template void print_buf<cl_mem>(std::ostream&, const cl_mem*,
+                                       size_t, ArgType, bool, bool);
 
 class memory_object : public clobj<cl_mem> {
 private:
diff --git a/src/c_wrapper/platform.cpp b/src/c_wrapper/platform.cpp
index 7c955330af66ec0d85cfe075203bf017cd37d298..59f0bb13f8e9240fccf2e941612f75fa0a692966 100644
--- a/src/c_wrapper/platform.cpp
+++ b/src/c_wrapper/platform.cpp
@@ -5,6 +5,11 @@
 namespace pyopencl {
 
 template class clobj<cl_platform_id>;
+template void print_arg<cl_platform_id>(std::ostream&,
+                                        const cl_platform_id&, bool);
+template void print_clobj<platform>(std::ostream&, const platform*);
+template void print_buf<cl_platform_id>(std::ostream&, const cl_platform_id*,
+                                        size_t, ArgType, bool, bool);
 
 generic_info
 platform::get_info(cl_uint param_name) const
diff --git a/src/c_wrapper/platform.h b/src/c_wrapper/platform.h
index 00c24fa81144f16c095be76827f17d6b30a3eba2..4ef0ce8909877ee088fef4a4cf23a35c3bae8d17 100644
--- a/src/c_wrapper/platform.h
+++ b/src/c_wrapper/platform.h
@@ -8,6 +8,10 @@ namespace pyopencl {
 // {{{ platform
 
 extern template class clobj<cl_platform_id>;
+extern template void print_arg<cl_platform_id>(std::ostream&,
+                                               const cl_platform_id&, bool);
+extern template void print_buf<cl_platform_id>(
+    std::ostream&, const cl_platform_id*, size_t, ArgType, bool, bool);
 
 class platform : public clobj<cl_platform_id> {
 public:
@@ -17,6 +21,8 @@ public:
     generic_info get_info(cl_uint param_name) const;
 };
 
+extern template void print_clobj<platform>(std::ostream&, const platform*);
+
 // }}}
 
 }
diff --git a/src/c_wrapper/program.cpp b/src/c_wrapper/program.cpp
index 2500fd63ddaa1bef189b1e90ec4fe483edaf3bf8..e5fd8da9e22058ab97944e3a9faeb2a86a4fc30e 100644
--- a/src/c_wrapper/program.cpp
+++ b/src/c_wrapper/program.cpp
@@ -6,6 +6,10 @@
 namespace pyopencl {
 
 template class clobj<cl_program>;
+template void print_arg<cl_program>(std::ostream&, const cl_program&, bool);
+template void print_clobj<program>(std::ostream&, const program*);
+template void print_buf<cl_program>(std::ostream&, const cl_program*,
+                                    size_t, ArgType, bool, bool);
 
 PYOPENCL_USE_RESULT static PYOPENCL_INLINE program*
 new_program(cl_program prog, program_kind_type progkind=KND_UNKNOWN)
diff --git a/src/c_wrapper/program.h b/src/c_wrapper/program.h
index 08357a27c537bdf60ec1bf231d2c7b8dbd29471f..8e148fffaf3edd730b7875ebc94766adb47db94f 100644
--- a/src/c_wrapper/program.h
+++ b/src/c_wrapper/program.h
@@ -10,6 +10,10 @@ class device;
 // {{{ program
 
 extern template class clobj<cl_program>;
+extern template void print_arg<cl_program>(std::ostream&,
+                                           const cl_program&, bool);
+extern template void print_buf<cl_program>(std::ostream&, const cl_program*,
+                                           size_t, ArgType, bool, bool);
 
 class program : public clobj<cl_program> {
 private:
@@ -81,6 +85,8 @@ public:
     // #endif
 };
 
+extern template void print_clobj<program>(std::ostream&, const program*);
+
 // }}}
 
 }
diff --git a/src/c_wrapper/sampler.cpp b/src/c_wrapper/sampler.cpp
index b961e00fa3fad5e8843ffef6a6de146522d4cfba..1ade54fa54d1440db1991d9b34abaab16d80e5d9 100644
--- a/src/c_wrapper/sampler.cpp
+++ b/src/c_wrapper/sampler.cpp
@@ -5,6 +5,10 @@
 namespace pyopencl {
 
 template class clobj<cl_sampler>;
+template void print_arg<cl_sampler>(std::ostream&, const cl_sampler&, bool);
+template void print_clobj<sampler>(std::ostream&, const sampler*);
+template void print_buf<cl_sampler>(std::ostream&, const cl_sampler*,
+                                    size_t, ArgType, bool, bool);
 
 sampler::~sampler()
 {
diff --git a/src/c_wrapper/sampler.h b/src/c_wrapper/sampler.h
index 30b1508bc2d984e2146e57d61d63b44b37dd4753..8ac5db7d476172496d150165bc756b4b7335b90a 100644
--- a/src/c_wrapper/sampler.h
+++ b/src/c_wrapper/sampler.h
@@ -8,6 +8,10 @@ namespace pyopencl {
 // {{{ sampler
 
 extern template class clobj<cl_sampler>;
+extern template void print_arg<cl_sampler>(std::ostream&,
+                                           const cl_sampler&, bool);
+extern template void print_buf<cl_sampler>(std::ostream&, const cl_sampler*,
+                                           size_t, ArgType, bool, bool);
 
 class sampler : public clobj<cl_sampler> {
 public:
@@ -24,6 +28,8 @@ public:
     generic_info get_info(cl_uint param_name) const;
 };
 
+extern template void print_clobj<sampler>(std::ostream&, const sampler*);
+
 // }}}
 
 }
diff --git a/src/c_wrapper/utils.h b/src/c_wrapper/utils.h
index c2f01c8ec0153ea94580040ee8d2e96a040a7b06..0359b6ae600543fd72e76806f4cc88a2d5924621 100644
--- a/src/c_wrapper/utils.h
+++ b/src/c_wrapper/utils.h
@@ -79,8 +79,10 @@ print_buf(std::ostream &stm, const T *p, size_t len,
         switch (arg_type) {
         case ArgType::SizeOf:
             stm << ele_size * len << ", ";
+            break;
         case ArgType::Length:
             stm << len << ", ";
+            break;
         default:
             break;
         }
@@ -90,6 +92,17 @@ print_buf(std::ostream &stm, const T *p, size_t len,
         }
     }
 }
+
+template<typename T>
+void
+print_arg(std::ostream &stm, const T &v, bool out)
+{
+    if (!out) {
+        stm << (const void*)&v;
+    } else {
+        stm << "*(" << (const void*)&v << "): " << v;
+    }
+}
 extern template void print_buf<char>(std::ostream&, const char*, size_t,
                                      ArgType, bool, bool);
 extern template void print_buf<cl_int>(std::ostream&, const cl_int*, size_t,
@@ -313,11 +326,7 @@ public:
     PYOPENCL_INLINE void
     print(std::ostream &stm, bool out=false)
     {
-        if (!out) {
-            stm << m_t;
-        } else {
-            stm << "*(" << m_t << "): " << *m_t;
-        }
+        print_arg(stm, *m_t, out);
     }
 };