From 8333f4313cb0d620163deb278d2928721a1e73d6 Mon Sep 17 00:00:00 2001
From: Yichao Yu <yyc1992@gmail.com>
Date: Thu, 19 Jun 2014 01:22:25 +0800
Subject: [PATCH] minor tweaks, extern templates, fix print_buf

---
 src/c_wrapper/buffer.cpp        |   2 +
 src/c_wrapper/buffer.h          |   2 +
 src/c_wrapper/clhelper.h        | 138 ++++++++++++++++----------------
 src/c_wrapper/command_queue.cpp |   5 ++
 src/c_wrapper/command_queue.h   |   7 ++
 src/c_wrapper/context.cpp       |   4 +
 src/c_wrapper/context.h         |   6 ++
 src/c_wrapper/device.cpp        |   5 ++
 src/c_wrapper/device.h          |   6 ++
 src/c_wrapper/error.h           |   8 +-
 src/c_wrapper/event.cpp         |   4 +
 src/c_wrapper/event.h           |   5 ++
 src/c_wrapper/gl_obj.cpp        |   4 +
 src/c_wrapper/gl_obj.h          |   4 +
 src/c_wrapper/image.cpp         |   2 +
 src/c_wrapper/image.h           |   2 +
 src/c_wrapper/kernel.cpp        |   4 +
 src/c_wrapper/kernel.h          |   6 ++
 src/c_wrapper/memory_map.cpp    |   3 +
 src/c_wrapper/memory_map.h      |   3 +
 src/c_wrapper/memory_object.cpp |   3 +
 src/c_wrapper/memory_object.h   |   3 +
 src/c_wrapper/platform.cpp      |   5 ++
 src/c_wrapper/platform.h        |   6 ++
 src/c_wrapper/program.cpp       |   4 +
 src/c_wrapper/program.h         |   6 ++
 src/c_wrapper/sampler.cpp       |   4 +
 src/c_wrapper/sampler.h         |   6 ++
 src/c_wrapper/utils.h           |  19 +++--
 29 files changed, 196 insertions(+), 80 deletions(-)

diff --git a/src/c_wrapper/buffer.cpp b/src/c_wrapper/buffer.cpp
index a4d999dd..a9223e8f 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 4681b192..14b8118f 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 17962280..d8e5556b 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 583374a4..bede3cbf 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 c5970d31..ef398459 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 628b6c5e..fd8f4855 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 44ffc92a..be18a3fc 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 54d1b7de..1d94bb92 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 402461eb..1d0d0928 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 dfcef093..e847a1a0 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 e618937a..f9004448 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 964efe0d..2160b07c 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 690a7ee2..7358011b 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 3ff225db..f14637a5 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 986e792c..b1700582 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 74faa71d..72f062bf 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 a8dec604..a4a19d5f 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 5029d0c3..fda782d0 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 d82b571d..3b4c15b5 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 714a451d..8836b374 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 b2f0f02d..b347e743 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 42c60bc1..39df1bc7 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 7c955330..59f0bb13 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 00c24fa8..4ef0ce89 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 2500fd63..e5fd8da9 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 08357a27..8e148fff 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 b961e00f..1ade54fa 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 30b1508b..8ac5db7d 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 c2f01c8e..0359b6ae 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);
     }
 };
 
-- 
GitLab