diff --git a/xbob/io/externals.cpp b/xbob/io/externals.cpp
index f7abc1d88393019b155f5368e4b0e0b0b3e44532..273b360c27a82a10ed602097acff85702af49750 100644
--- a/xbob/io/externals.cpp
+++ b/xbob/io/externals.cpp
@@ -7,6 +7,9 @@
 
 #include <Python.h>
 
+#ifdef NO_IMPORT_ARRAY
+#undef NO_IMPORT_ARRAY
+#endif
 #define XBOB_IO_MODULE
 #include <xbob.io/config.h>
 
@@ -19,6 +22,9 @@
 #include <bob/io/CodecRegistry.h>
 #include <bob/io/VideoUtilities.h>
 
+#include <xbob.blitz/capi.h>
+#include <xbob.blitz/cleanup.h>
+
 extern "C" {
 
 #ifdef NO_IMPORT_ARRAY
@@ -61,16 +67,16 @@ extern "C" {
 static int dict_set(PyObject* d, const char* key, const char* value) {
   PyObject* v = Py_BuildValue("s", value);
   if (!v) return 0;
+  auto v_ = make_safe(v);
   int retval = PyDict_SetItemString(d, key, v);
-  Py_DECREF(v);
   if (retval == 0) return 1; //all good
   return 0; //a problem occurred
 }
 
 static int dict_steal(PyObject* d, const char* key, PyObject* value) {
   if (!value) return 0;
+  auto value_ = make_safe(value);
   int retval = PyDict_SetItemString(d, key, value);
-  Py_DECREF(value);
   if (retval == 0) return 1; //all good
   return 0; //a problem occurred
 }
@@ -169,38 +175,32 @@ static PyObject* hdf5_version() {
 static PyObject* ffmpeg_version() {
   PyObject* retval = PyDict_New();
   if (!retval) return 0;
+  auto retval_ = make_safe(retval);
 
 #if WITH_FFMPEG
 # if defined(FFMPEG_VERSION)
   if (std::strlen(FFMPEG_VERSION)) {
-    if (!dict_set(retval, "ffmpeg", FFMPEG_VERSION)) {
-      Py_DECREF(retval);
-      return 0;
-    }
+    if (!dict_set(retval, "ffmpeg", FFMPEG_VERSION)) return 0;
   }
 # endif
   if (!dict_set(retval, "avformat", BOOST_PP_STRINGIZE(LIBAVFORMAT_VERSION))) {
-    Py_DECREF(retval);
     return 0;
   }
   if (!dict_set(retval, "avcodec", BOOST_PP_STRINGIZE(LIBAVCODEC_VERSION))) {
-    Py_DECREF(retval);
     return 0;
   }
   if (!dict_set(retval, "avutil", BOOST_PP_STRINGIZE(LIBAVUTIL_VERSION))) {
-    Py_DECREF(retval);
     return 0;
   }
   if (!dict_set(retval, "swscale", BOOST_PP_STRINGIZE(LIBSWSCALE_VERSION))) {
-    Py_DECREF(retval);
     return 0;
   }
 #else
   if (!dict_set(retval, "ffmpeg", "unavailable")) {
-    Py_DECREF(retval);
     return 0;
   }
 #endif
+  Py_INCREF(retval);
   return retval;
 }
 
@@ -278,47 +278,25 @@ static PyObject* build_version_dictionary() {
 
   PyObject* retval = PyDict_New();
   if (!retval) return 0;
+  auto retval_ = make_safe(retval);
 
-  if (!dict_steal(retval, "HDF5", hdf5_version())) {
-    Py_DECREF(retval);
-    return 0;
-  }
+  if (!dict_steal(retval, "HDF5", hdf5_version())) return 0;
 
-  if (!dict_steal(retval, "FFmpeg", ffmpeg_version())) {
-    Py_DECREF(retval);
-    return 0;
-  }
+  if (!dict_steal(retval, "FFmpeg", ffmpeg_version())) return 0;
 
-  if (!dict_steal(retval, "libjpeg", libjpeg_version())) {
-    Py_DECREF(retval);
-    return 0;
-  }
+  if (!dict_steal(retval, "libjpeg", libjpeg_version())) return 0;
 
-  if (!dict_set(retval, "libnetpbm", "Unknown version")) {
-    Py_DECREF(retval);
-    return 0;
-  }
+  if (!dict_set(retval, "libnetpbm", "Unknown version")) return 0;
 
-  if (!dict_steal(retval, "libpng", libpng_version())) {
-    Py_DECREF(retval);
-    return 0;
-  }
+  if (!dict_steal(retval, "libpng", libpng_version())) return 0;
 
-  if (!dict_steal(retval, "libtiff", libtiff_version())) {
-    Py_DECREF(retval);
-    return 0;
-  }
+  if (!dict_steal(retval, "libtiff", libtiff_version())) return 0;
 
-  if (!dict_steal(retval, "giflib", giflib_version())) {
-    Py_DECREF(retval);
-    return 0;
-  }
+  if (!dict_steal(retval, "giflib", giflib_version())) return 0;
 
-  if (!dict_steal(retval, "MatIO", matio_version())) {
-    Py_DECREF(retval);
-    return 0;
-  }
+  if (!dict_steal(retval, "MatIO", matio_version())) return 0;
 
+  Py_INCREF(retval);
   return retval;
 }
 
@@ -537,21 +515,16 @@ static PyObject* get_video_codecs(void (*f)(std::map<std::string, const AVCodec*
 
   PyObject* retval = PyDict_New();
   if (!retval) return 0;
+  auto retval_ = make_safe(retval);
 
   for (auto k=m.begin(); k!=m.end(); ++k) {
     PyObject* pyvalue = describe_codec(k->second);
-    if (!pyvalue) {
-      Py_DECREF(retval);
-      return 0;
-    }
-    if (PyDict_SetItemString(retval, k->first.c_str(), pyvalue) != 0) {
-      Py_DECREF(pyvalue);
-      Py_DECREF(retval);
-      return 0;
-    }
-    Py_DECREF(pyvalue);
+    if (!pyvalue) return 0;
+    auto pyvalue_ = make_safe(pyvalue);
+    if (PyDict_SetItemString(retval, k->first.c_str(), pyvalue) != 0) return 0;
   }
 
+  Py_INCREF(retval);
   return retval;
 
 }
@@ -592,60 +565,39 @@ static PyObject* get_video_iformats(void (*f)(std::map<std::string, AVInputForma
 
   PyObject* retval = PyDict_New();
   if (!retval) return 0;
+  auto retval_ = make_safe(retval);
 
   for (auto k=m.begin(); k!=m.end(); ++k) {
 
     PyObject* property = PyDict_New();
-    if (!property) {
-      Py_DECREF(retval);
-      return 0;
-    }
+    if (!property) return 0;
+    auto property_ = make_safe(property);
 
-    if (!dict_set(property, "name", k->second->name)) {
-      Py_DECREF(property);
-      Py_DECREF(retval);
-      return 0;
-    }
+    if (!dict_set(property, "name", k->second->name)) return 0;
 
-    if (!dict_set(property, "long_name", k->second->long_name)) {
-      Py_DECREF(property);
-      Py_DECREF(retval);
-      return 0;
-    }
+    if (!dict_set(property, "long_name", k->second->long_name)) return 0;
 
     // get extensions
     std::vector<std::string> exts;
     bob::io::detail::ffmpeg::tokenize_csv(k->second->extensions, exts);
 
     PyObject* ext_list = PyList_New(0);
-    if (!ext_list) {
-      Py_DECREF(property);
-      Py_DECREF(retval);
-      return 0;
-    }
+    if (!ext_list) return 0;
+    auto ext_list_ = make_safe(ext_list);
 
     for (auto ext=exts.begin(); ext!=exts.end(); ++ext) {
-      if (!list_append(ext_list, ext->c_str())) {
-        Py_DECREF(ext_list);
-        Py_DECREF(property);
-        Py_DECREF(retval);
-        return 0;
-      }
+      if (!list_append(ext_list, ext->c_str())) return 0;
     }
 
-    if (!dict_steal(property, "extensions", ext_list)) {
-      Py_DECREF(property);
-      Py_DECREF(retval);
-      return 0;
-    }
+    Py_INCREF(ext_list);
+    if (!dict_steal(property, "extensions", ext_list)) return 0;
 
-    if (!dict_steal(retval, k->first.c_str(), property)) {
-      Py_DECREF(retval);
-      return 0;
-    }
+    Py_INCREF(property);
+    if (!dict_steal(retval, k->first.c_str(), property)) return 0;
 
   }
 
+  Py_INCREF(retval);
   return retval;
 
 }
@@ -687,59 +639,34 @@ static PyObject* get_video_oformats(bool supported) {
 
   PyObject* retval = PyDict_New();
   if (!retval) return 0;
+  auto retval_ = make_safe(retval);
 
   for (auto k=m.begin(); k!=m.end(); ++k) {
 
     PyObject* property = PyDict_New();
-    if (!property) {
-      Py_DECREF(retval);
-      return 0;
-    }
+    if (!property) return 0;
+    auto property_ = make_safe(property);
 
-    if (!dict_set(property, "name", k->second->name)) {
-      Py_DECREF(property);
-      Py_DECREF(retval);
-      return 0;
-    }
+    if (!dict_set(property, "name", k->second->name)) return 0;
 
-    if (!dict_set(property, "long_name", k->second->long_name)) {
-      Py_DECREF(property);
-      Py_DECREF(retval);
-      return 0;
-    }
+    if (!dict_set(property, "long_name", k->second->long_name)) return 0;
 
-    if (!dict_set(property, "mime_type", k->second->mime_type)) {
-      Py_DECREF(property);
-      Py_DECREF(retval);
-      return 0;
-    }
+    if (!dict_set(property, "mime_type", k->second->mime_type)) return 0;
 
     // get extensions
     std::vector<std::string> exts;
     bob::io::detail::ffmpeg::tokenize_csv(k->second->extensions, exts);
 
     PyObject* ext_list = PyList_New(0);
-    if (!ext_list) {
-      Py_DECREF(property);
-      Py_DECREF(retval);
-      return 0;
-    }
+    if (!ext_list) return 0;
+    auto ext_list_ = make_safe(ext_list);
 
     for (auto ext=exts.begin(); ext!=exts.end(); ++ext) {
-
-      if (!list_append(ext_list, ext->c_str())) {
-        Py_DECREF(ext_list);
-        Py_DECREF(property);
-        Py_DECREF(retval);
-        return 0;
-      }
+      if (!list_append(ext_list, ext->c_str())) return 0;
     }
 
-    if (!dict_steal(property, "extensions", ext_list)) {
-      Py_DECREF(property);
-      Py_DECREF(retval);
-      return 0;
-    }
+    Py_INCREF(ext_list);
+    if (!dict_steal(property, "extensions", ext_list)) return 0;
 
     /**  get recommended codec **/
     PyObject* default_codec = 0;
@@ -747,11 +674,7 @@ static PyObject* get_video_oformats(bool supported) {
       AVCodec* codec = avcodec_find_encoder(k->second->video_codec);
       if (codec) {
         default_codec = describe_codec(codec);
-        if (!default_codec) {
-          Py_DECREF(property);
-          Py_DECREF(retval);
-          return 0;
-        }
+        if (!default_codec) return 0;
       }
     }
 
@@ -760,11 +683,7 @@ static PyObject* get_video_oformats(bool supported) {
       default_codec = Py_None;
     }
 
-    if (!dict_steal(property, "default_codec", default_codec)) {
-      Py_DECREF(property);
-      Py_DECREF(retval);
-      return 0;
-    }
+    if (!dict_steal(property, "default_codec", default_codec)) return 0;
 
     /** get supported codec list **/
     if (supported) {
@@ -772,41 +691,27 @@ static PyObject* get_video_oformats(bool supported) {
       bob::io::detail::ffmpeg::oformat_supported_codecs(k->second->name, codecs);
 
       PyObject* supported_codecs = PyDict_New();
-      if (!supported_codecs) {
-        Py_DECREF(property);
-        Py_DECREF(retval);
-        return 0;
-      }
+      if (!supported_codecs) return 0;
+      auto supported_codecs_ = make_safe(supported_codecs);
 
       for (auto c=codecs.begin(); c!=codecs.end(); ++c) {
         PyObject* codec_descr = describe_codec(*c);
-        if (!codec_descr) {
-          Py_DECREF(supported_codecs);
-          Py_DECREF(property);
-          Py_DECREF(retval);
-          return 0;
-        }
-        if (!dict_steal(supported_codecs, (*c)->name, codec_descr)) {
-          Py_DECREF(property);
-          Py_DECREF(retval);
-          return 0;
-        }
+        auto codec_descr_ = make_safe(codec_descr);
+        if (!codec_descr) return 0;
+        Py_INCREF(codec_descr);
+        if (!dict_steal(supported_codecs, (*c)->name, codec_descr)) return 0;
       }
 
-      if (!dict_steal(property, "supported_codecs", supported_codecs)) {
-        Py_DECREF(property);
-        Py_DECREF(retval);
-        return 0;
-      }
+      Py_INCREF(supported_codecs);
+      if (!dict_steal(property, "supported_codecs", supported_codecs)) return 0;
     }
 
-    if (!dict_steal(retval, k->first.c_str(), property)) {
-      Py_DECREF(retval);
-      return 0;
-    }
+    Py_INCREF(property);
+    if (!dict_steal(retval, k->first.c_str(), property)) return 0;
 
   }
 
+  Py_INCREF(retval);
   return retval;
 
 }
@@ -849,19 +754,13 @@ static PyObject* PyBobIo_Extensions(PyObject*) {
 
   PyObject* retval = PyDict_New();
   if (!retval) return 0;
+  auto retval_ = make_safe(retval);
 
   for (auto it=table.begin(); it!=table.end(); ++it) {
     PyObject* pyvalue = make_object(it->second.c_str());
-    if (!pyvalue) {
-      Py_DECREF(retval);
-      return 0;
-    }
-    if (PyDict_SetItemString(retval, it->first.c_str(), pyvalue) != 0) {
-      Py_DECREF(pyvalue);
-      Py_DECREF(retval);
-      return 0;
-    }
-    Py_DECREF(pyvalue);
+    if (!pyvalue) return 0;
+    auto pyvalue_ = make_safe(retval);
+    if (PyDict_SetItemString(retval, it->first.c_str(), pyvalue) != 0) return 0;
   }
   return retval;
 
@@ -952,27 +851,34 @@ static PyModuleDef module_definition = {
 };
 #endif
 
-PyMODINIT_FUNC XBOB_EXT_ENTRY_NAME (void) {
+static PyObject* create_module (void) {
 
 # if PY_VERSION_HEX >= 0x03000000
   PyObject* m = PyModule_Create(&module_definition);
-  if (!m) return 0;
 # else
-  PyObject* m = Py_InitModule3(XBOB_EXT_MODULE_NAME, 
-      module_methods, module_docstr);
-  if (!m) return;
+  PyObject* m = Py_InitModule3(XBOB_EXT_MODULE_NAME, module_methods, module_docstr);
 # endif
+  if (!m) return 0;
+  auto m_ = make_safe(m); ///< protects against early returns
 
-  /* register some constants */
-  PyModule_AddIntConstant(m, "__api_version__", XBOB_IO_API_VERSION);
-  PyModule_AddStringConstant(m, "__version__", XBOB_EXT_MODULE_VERSION);
-  PyModule_AddObject(m, "versions", build_version_dictionary());
+  /* register version numbers and constants */
+  if (PyModule_AddIntConstant(m, "__api_version__", XBOB_IO_API_VERSION) < 0) 
+    return 0;
+  if (PyModule_AddStringConstant(m, "__version__", XBOB_EXT_MODULE_VERSION) < 0)
+    return 0;
+  if (PyModule_AddObject(m, "versions", build_version_dictionary()) < 0) return 0;
 
-  /* imports the NumPy C-API */
-  import_array();
+  /* imports xbob.blitz C-API + dependencies */
+  if (import_xbob_blitz() < 0) return 0;
 
-# if PY_VERSION_HEX >= 0x03000000
+  Py_INCREF(m);
   return m;
-# endif
 
 }
+
+PyMODINIT_FUNC XBOB_EXT_ENTRY_NAME (void) {
+# if PY_VERSION_HEX >= 0x03000000
+  return
+# endif
+    create_module();
+}
diff --git a/xbob/io/file.cpp b/xbob/io/file.cpp
index d7d13c6ad3723d870be68ece478d5e19565a3a0d..e143e456ff753cbec7b4a40efe934bdc8a1c735e 100644
--- a/xbob/io/file.cpp
+++ b/xbob/io/file.cpp
@@ -256,6 +256,7 @@ static PyObject* PyBobIoFile_GetIndex (PyBobIoFileObject* self, Py_ssize_t i) {
 
   PyObject* retval = PyArray_SimpleNew(info.nd, shape, type_num);
   if (!retval) return 0;
+  auto retval_ = make_safe(retval);
 
   try {
     bobskin skin((PyArrayObject*)retval, info.dtype);
@@ -263,15 +264,14 @@ static PyObject* PyBobIoFile_GetIndex (PyBobIoFileObject* self, Py_ssize_t i) {
   }
   catch (std::exception& e) {
     if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError, e.what());
-    Py_DECREF(retval);
     return 0;
   }
   catch (...) {
     if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught unknown exception while reading object #%" PY_FORMAT_SIZE_T "d from file `%s'", i, self->f->filename().c_str());
-    Py_DECREF(retval);
     return 0;
   }
 
+  Py_INCREF(retval);
   return retval;
 
 }
@@ -300,23 +300,19 @@ static PyObject* PyBobIoFile_GetSlice (PyBobIoFileObject* self, PySliceObject* s
 
   PyObject* retval = PyArray_SimpleNew(info.nd+1, shape, type_num);
   if (!retval) return 0;
+  auto retval_ = make_safe(retval);
 
   Py_ssize_t counter = 0;
   for (auto i = start; (start<=stop)?i<stop:i>stop; i+=step) {
 
     //get slice to fill
     PyObject* islice = Py_BuildValue("n", counter++);
-    if (!islice) {
-      Py_DECREF(retval);
-      return 0;
-    }
+    if (!islice) return 0;
+    auto islice_ = make_safe(islice);
 
     PyObject* item = PyObject_GetItem(retval, islice);
-    Py_DECREF(islice);
-    if (!item) {
-      Py_DECREF(retval);
-      return 0;
-    }
+    if (!item) return 0;
+    auto item_ = make_safe(item);
 
     try {
       bobskin skin((PyArrayObject*)item, info.dtype);
@@ -324,19 +320,16 @@ static PyObject* PyBobIoFile_GetSlice (PyBobIoFileObject* self, PySliceObject* s
     }
     catch (std::exception& e) {
       if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError, e.what());
-      Py_DECREF(retval);
-      Py_DECREF(item);
       return 0;
     }
     catch (...) {
       if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught unknown exception while reading object #%" PY_FORMAT_SIZE_T "d from file `%s'", i, self->f->filename().c_str());
-      Py_DECREF(retval);
-      Py_DECREF(item);
       return 0;
     }
 
   }
 
+  Py_INCREF(retval);
   return retval;
 
 }
@@ -399,6 +392,7 @@ static PyObject* PyBobIoFile_Read(PyBobIoFileObject* self, PyObject *args, PyObj
 
   PyObject* retval = PyArray_SimpleNew(info.nd, shape, type_num);
   if (!retval) return 0;
+  auto retval_ = make_safe(retval);
 
   try {
     bobskin skin((PyArrayObject*)retval, info.dtype);
@@ -406,20 +400,18 @@ static PyObject* PyBobIoFile_Read(PyBobIoFileObject* self, PyObject *args, PyObj
   }
   catch (std::runtime_error& e) {
     if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught std::runtime_error while reading all contents of file `%s': %s", self->f->filename().c_str(), e.what());
-    Py_DECREF(retval);
     return 0;
   }
   catch (std::exception& e) {
     if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError, e.what());
-    Py_DECREF(retval);
     return 0;
   }
   catch (...) {
     if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught unknown while reading all contents of file `%s'", self->f->filename().c_str());
-    Py_DECREF(retval);
     return 0;
   }
 
+  Py_INCREF(retval);
   return retval;
 
 }
diff --git a/xbob/io/hdf5.cpp b/xbob/io/hdf5.cpp
index 2bdb2e03af85985d9a65bd2c5bad854d81be9f38..a3ce2b27de1792751d01b29514af6157dbfdc09f 100644
--- a/xbob/io/hdf5.cpp
+++ b/xbob/io/hdf5.cpp
@@ -384,6 +384,7 @@ static int PyBobIo_H5AsTypenum (bob::io::hdf5type type) {
 }
 
 static PyObject* PyBobIo_HDF5TypeAsTuple (const bob::io::HDF5Type& t) {
+
   const bob::io::HDF5Shape& sh = t.shape();
   size_t ndim = sh.n();
   const hsize_t* shptr = sh.get();
@@ -397,18 +398,22 @@ static PyObject* PyBobIo_HDF5TypeAsTuple (const bob::io::HDF5Type& t) {
   PyObject* dtype = reinterpret_cast<PyObject*>(PyArray_DescrFromType(type_num));
   if (!dtype) return 0;
 
-  PyObject* retval = Py_BuildValue("NN", dtype, PyTuple_New(ndim));
-  if (!retval) {
-    Py_DECREF(dtype);
-    return 0;
-  }
+  PyObject* shape = PyTuple_New(ndim);
+  if (!shape) return 0;
+
+  PyObject* retval = Py_BuildValue("NN", dtype, shape); //steals references
+  if (!retval) return 0;
+  auto retval_ = make_safe(retval);
 
-  PyObject* shape = PyTuple_GET_ITEM(retval, 1);
   for (Py_ssize_t i=0; i<(Py_ssize_t)ndim; ++i) {
-    PyTuple_SET_ITEM(shape, i, Py_BuildValue("n", shptr[i]));
+    PyObject* value = Py_BuildValue("n", shptr[i]);
+    if (!value) return 0;
+    PyTuple_SET_ITEM(shape, i, value);
   }
 
+  Py_INCREF(retval);
   return retval;
+
 }
 
 static PyObject* PyBobIo_HDF5DescriptorAsTuple (const bob::io::HDF5Descriptor& d) {
@@ -416,11 +421,14 @@ static PyObject* PyBobIo_HDF5DescriptorAsTuple (const bob::io::HDF5Descriptor& d
   PyObject* type = PyBobIo_HDF5TypeAsTuple(d.type);
   if (!type) return 0;
   PyObject* size = Py_BuildValue("n", d.size);
-  if (!type) return 0;
+  if (!size) {
+    Py_DECREF(type);
+    return 0;
+  }
   PyObject* expand = d.expandable? Py_True : Py_False;
   Py_INCREF(expand);
 
-  return Py_BuildValue("NNN", type, size, expand);
+  return Py_BuildValue("NNN", type, size, expand); //steals references
 
 }
 
@@ -434,26 +442,29 @@ static PyObject* PyBobIoHDF5File_Describe(PyBobIoHDF5FileObject* self, PyObject
   if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &key)) return 0;
 
   PyObject* retval = 0;
+  std::shared_ptr<PyObject> retval_;
 
   try {
     const std::vector<bob::io::HDF5Descriptor>& dv = self->f->describe(key);
     retval = PyTuple_New(dv.size());
+    retval_ = make_safe(retval);
+
     for (size_t k=0; k<dv.size(); ++k) {
       PyObject* entry = PyBobIo_HDF5DescriptorAsTuple(dv[k]);
-      if (!entry) {
-        Py_DECREF(retval);
-        return 0;
-      }
+      if (!entry) return 0;
       PyTuple_SET_ITEM(retval, k, entry);
     }
   }
   catch (std::exception& e) {
     PyErr_SetString(PyExc_RuntimeError, e.what());
+    return 0;
   }
   catch (...) {
     PyErr_Format(PyExc_RuntimeError, "unknown exception caught while getting description for dataset `%s' in HDF5 file `%s'", key, self->f->filename().c_str());
+    return 0;
   }
 
+  Py_INCREF(retval);
   return retval;
 }
 
@@ -572,11 +583,14 @@ static PyObject* PyBobIoHDF5File_Paths(PyBobIoHDF5FileObject* self, PyObject *ar
   if (pyrel && PyObject_IsTrue(pyrel)) relative = true;
 
   PyObject* retval = 0;
+  std::shared_ptr<PyObject> retval_;
 
   try {
     std::vector<std::string> values;
     self->f->paths(values, relative);
     retval = PyTuple_New(values.size());
+    if (!retval) return 0;
+    retval_ = make_safe(retval);
     for (size_t i=0; i<values.size(); ++i) {
       PyTuple_SET_ITEM(retval, i, Py_BuildValue("s", values[i].c_str()));
     }
@@ -590,6 +604,7 @@ static PyObject* PyBobIoHDF5File_Paths(PyBobIoHDF5FileObject* self, PyObject *ar
     return 0;
   }
 
+  Py_INCREF(retval);
   return retval;
 }
 
@@ -749,21 +764,21 @@ static PyObject* PyBobIoHDF5File_Xread(PyBobIoHDF5FileObject* self,
 
   PyObject* retval = PyArray_SimpleNew(shape.n(), pyshape, type_num);
   if (!retval) return 0;
+  auto retval_ = make_safe(retval);
 
   try {
     self->f->read_buffer(p, pos, type, PyArray_DATA((PyArrayObject*)retval));
   }
   catch (std::exception& e) {
     PyErr_SetString(PyExc_RuntimeError, e.what());
-    Py_DECREF(retval);
     return 0;
   }
   catch (...) {
     PyErr_Format(PyExc_RuntimeError, "caught unknown exception while reading dataset `%s' at position %d with descriptor `%s' from HDF5 file `%s'", p, pos, type.str().c_str(), self->f->filename().c_str());
-    Py_DECREF(retval);
     return 0;
   }
 
+  Py_INCREF(retval);
   return retval;
 }
 
@@ -823,16 +838,15 @@ static PyObject* PyBobIoHDF5File_ListRead(PyBobIoHDF5FileObject* self, PyObject
 
   PyObject* retval = PyTuple_New((*D)[0].size);
   if (!retval) return 0;
+  auto retval_ = make_safe(retval);
 
   for (uint64_t k=0; k<(*D)[0].size; ++k) {
     PyObject* item = PyBobIoHDF5File_Xread(self, key, 0, k);
-    if (!item) {
-      Py_DECREF(retval);
-      return 0;
-    }
+    if (!item) return 0;
     PyTuple_SET_ITEM(retval, k, item);
   }
 
+  Py_INCREF(retval);
   return retval;
 
 }
@@ -1116,6 +1130,8 @@ static PyObject* PyBobIoHDF5File_Replace(PyBobIoHDF5FileObject* self, PyObject*
   bob::io::HDF5Type type;
   PyObject* converted = 0;
   int is_array = PyBobIoHDF5File_GetObjectType(data, type, &converted);
+  auto converted_ = make_xsafe(converted);
+
   if (is_array < 0) { ///< error condition, signal
     PyErr_Format(PyExc_TypeError, "error replacing position %" PY_FORMAT_SIZE_T "d of dataset `%s' at HDF5 file `%s': no support for storing objects of type `%s' on HDF5 files", pos, path, self->f->filename().c_str(), Py_TYPE(data)->tp_name);
     return 0;
@@ -1182,7 +1198,6 @@ static PyObject* PyBobIoHDF5File_Replace(PyBobIoHDF5FileObject* self, PyObject*
 
         case 3: //converted numpy.ndarray
           self->f->write_buffer(path, pos, type, PyArray_DATA((PyArrayObject*)converted));
-          Py_DECREF(converted);
           break;
 
         default:
@@ -1195,12 +1210,10 @@ static PyObject* PyBobIoHDF5File_Replace(PyBobIoHDF5FileObject* self, PyObject*
   }
   catch (std::exception& e) {
     PyErr_SetString(PyExc_RuntimeError, e.what());
-    Py_XDECREF(converted);
     return 0;
   }
   catch (...) {
     PyErr_Format(PyExc_RuntimeError, "cannot replace object in position %" PY_FORMAT_SIZE_T "d at HDF5 file `%s': unknown exception caught", pos, self->f->filename().c_str());
-    Py_XDECREF(converted);
     return 0;
   }
 
@@ -1250,6 +1263,8 @@ static int PyBobIoHDF5File_InnerAppend(PyBobIoHDF5FileObject* self, const char*
   bob::io::HDF5Type type;
   PyObject* converted = 0;
   int is_array = PyBobIoHDF5File_GetObjectType(data, type, &converted);
+  auto converted_ = make_xsafe(converted);
+
   if (is_array < 0) { ///< error condition, signal
     PyErr_Format(PyExc_TypeError, "error appending to object `%s' of HDF5 file `%s': no support for storing objects of type `%s' on HDF5 files", path, self->f->filename().c_str(), Py_TYPE(data)->tp_name);
     return 0;
@@ -1319,7 +1334,6 @@ static int PyBobIoHDF5File_InnerAppend(PyBobIoHDF5FileObject* self, const char*
         case 3: //converted numpy.ndarray
           if (!self->f->contains(path)) self->f->create(path, type, true, compression);
           self->f->extend_buffer(path, type, PyArray_DATA((PyArrayObject*)converted));
-          Py_DECREF(converted);
           break;
 
         default:
@@ -1363,15 +1377,12 @@ static PyObject* PyBobIoHDF5File_Append(PyBobIoHDF5FileObject* self, PyObject *a
   if (PyTuple_Check(data) || PyList_Check(data)) {
     PyObject* iter = PyObject_GetIter(data);
     if (!iter) return 0;
+    auto iter_ = make_safe(iter);
     while (PyObject* item = PyIter_Next(iter)) {
+      auto item_ = make_safe(item);
       int ok = PyBobIoHDF5File_InnerAppend(self, path, item, compression);
-      Py_DECREF(item);
-      if (!ok) {
-        Py_DECREF(iter);
-        return 0;
-      }
+      if (!ok) return 0;
     }
-    Py_DECREF(iter);
     Py_RETURN_NONE;
   }
 
@@ -1442,6 +1453,8 @@ static PyObject* PyBobIoHDF5File_Set(PyBobIoHDF5FileObject* self, PyObject* args
   bob::io::HDF5Type type;
   PyObject* converted = 0;
   int is_array = PyBobIoHDF5File_GetObjectType(data, type, &converted);
+  auto converted_ = make_xsafe(converted);
+
   if (is_array < 0) { ///< error condition, signal
     PyErr_Format(PyExc_TypeError, "error setting object `%s' of HDF5 file `%s': no support for storing objects of type `%s' on HDF5 files", path, self->f->filename().c_str(), Py_TYPE(data)->tp_name);
     return 0;
@@ -1512,7 +1525,6 @@ static PyObject* PyBobIoHDF5File_Set(PyBobIoHDF5FileObject* self, PyObject* args
         case 3: //converted numpy.ndarray
           if (!self->f->contains(path)) self->f->create(path, type, false, compression);
           self->f->write_buffer(path, 0, type, PyArray_DATA((PyArrayObject*)converted));
-          Py_DECREF(converted);
           break;
 
         default:
@@ -1700,21 +1712,21 @@ static PyObject* PyBobIoHDF5File_ReadAttribute(PyBobIoHDF5FileObject* self,
 
   PyObject* retval = PyArray_SimpleNew(shape.n(), pyshape, type_num);
   if (!retval) return 0;
+  auto retval_ = make_safe(retval);
 
   try {
     self->f->read_attribute(path, name, type, PyArray_DATA((PyArrayObject*)retval));
   }
   catch (std::exception& e) {
     PyErr_SetString(PyExc_RuntimeError, e.what());
-    Py_DECREF(retval);
     return 0;
   }
   catch (...) {
     PyErr_Format(PyExc_RuntimeError, "caught unknown exception while reading array attribute `%s' at resource `%s' with descriptor `%s' from HDF5 file `%s'", name, path, type.str().c_str(), self->f->filename().c_str());
-    Py_DECREF(retval);
     return 0;
   }
 
+  Py_INCREF(retval);
   return retval;
 }
 
@@ -1788,6 +1800,9 @@ static PyObject* PyBobIoHDF5File_GetAttributes(PyBobIoHDF5FileObject* self, PyOb
   std::map<std::string, bob::io::HDF5Type> attributes;
   self->f->listAttributes(path, attributes);
   PyObject* retval = PyDict_New();
+  if (!retval) return 0;
+  auto retval_ = make_safe(retval);
+
   for (auto k=attributes.begin(); k!=attributes.end(); ++k) {
     PyObject* item = 0;
     if (k->second.type() == bob::io::unsupported) {
@@ -1799,14 +1814,14 @@ static PyObject* PyBobIoHDF5File_GetAttributes(PyBobIoHDF5FileObject* self, PyOb
       Py_INCREF(Py_None);
     }
     else item = PyBobIoHDF5File_ReadAttribute(self, path, k->first.c_str(), k->second);
-    int status = PyDict_SetItemString(retval, k->first.c_str(), item);
-    Py_DECREF(item);
-    if (status != 0) {
-      Py_DECREF(retval);
-      return 0;
-    }
+
+    if (!item) return 0;
+    auto item_ = make_safe(item);
+
+    if (PyDict_SetItemString(retval, k->first.c_str(), item) != 0) return 0;
   }
 
+  Py_INCREF(retval);
   return retval;
 
 }
@@ -1937,7 +1952,6 @@ static PyObject* PyBobIoHDF5File_WriteAttribute(PyBobIoHDF5FileObject* self,
 
         case 3: //converted numpy.ndarray
           self->f->write_attribute(path, name, type, PyArray_DATA((PyArrayObject*)converted));
-          Py_DECREF(converted);
           break;
 
         default:
@@ -1947,12 +1961,10 @@ static PyObject* PyBobIoHDF5File_WriteAttribute(PyBobIoHDF5FileObject* self,
     }
     catch (std::exception& e) {
       PyErr_SetString(PyExc_RuntimeError, e.what());
-      Py_XDECREF(converted);
       return 0;
     }
     catch (...) {
       PyErr_Format(PyExc_RuntimeError, "caught unknown exception while writing array attribute `%s' at resource `%s' with descriptor `%s' at HDF5 file `%s'", name, path, type.str().c_str(), self->f->filename().c_str());
-      Py_XDECREF(converted);
       return 0;
     }
 
@@ -1976,6 +1988,8 @@ static PyObject* PyBobIoHDF5File_SetAttribute(PyBobIoHDF5FileObject* self, PyObj
   bob::io::HDF5Type type;
   PyObject* converted = 0;
   int is_array = PyBobIoHDF5File_GetObjectType(value, type, &converted);
+  auto converted_ = make_xsafe(converted);
+  
   if (is_array < 0) { ///< error condition, signal
     PyErr_Format(PyExc_TypeError, "error setting attribute `%s' of resource `%s' at HDF5 file `%s': no support for storing objects of type `%s' on HDF5 files", name, path, self->f->filename().c_str(), Py_TYPE(value)->tp_name);
     return 0;
@@ -2046,6 +2060,8 @@ static PyObject* PyBobIoHDF5File_SetAttributes(PyBobIoHDF5FileObject* self, PyOb
     if (!name) return 0;
 
     int is_array = PyBobIoHDF5File_GetObjectType(value, type, &converted);
+    auto converted_ = make_xsafe(converted);
+
     if (is_array < 0) { ///< error condition, signal
       PyErr_Format(PyExc_TypeError, "error setting attribute `%s' of resource `%s' at HDF5 file `%s': no support for storing objects of type `%s' on HDF5 files", name.get(), path, self->f->filename().c_str(), Py_TYPE(value)->tp_name);
       return 0;
@@ -2159,28 +2175,23 @@ static PyObject* PyBobIoHDF5File_DelAttributes(PyBobIoHDF5FileObject* self, PyOb
   if (attrs) {
     PyObject* iter = PyObject_GetIter(attrs);
     if (!iter) return 0;
+    auto iter_ = make_safe(iter);
     while (PyObject* item = PyIter_Next(iter)) {
+      auto item_ = make_safe(item);
       auto name = PyBobIo_GetString(item);
-      Py_DECREF(item);
-      if (!name) {
-        Py_DECREF(iter);
-        return 0;
-      }
+      if (!name) return 0;
       try {
         self->f->deleteAttribute(path, name.get());
       }
       catch (std::exception& e) {
         PyErr_SetString(PyExc_RuntimeError, e.what());
-        Py_DECREF(iter);
         return 0;
       }
       catch (...) {
         PyErr_Format(PyExc_RuntimeError, "cannot delete attribute `%s' at resource `%s' of HDF5 file `%s': unknown exception caught", name.get(), path, self->f->filename().c_str());
-        Py_DECREF(iter);
         return 0;
       }
     }
-    Py_DECREF(iter);
     Py_RETURN_NONE;
   }
 
diff --git a/xbob/io/include/xbob.io/api.h b/xbob/io/include/xbob.io/api.h
index b605378755092a040e896a525e079e4526dc104d..ecf4ffc32cb9e5e5b7c5c97fda6971deeda0ddce 100644
--- a/xbob/io/include/xbob.io/api.h
+++ b/xbob/io/include/xbob.io/api.h
@@ -207,18 +207,6 @@ typedef struct {
 
   /* This section is used in modules that use `xbob.io's' C-API */
 
-/************************************************************************
- * Macros to avoid symbol collision and allow for separate compilation. *
- * We pig-back on symbols already defined for NumPy and apply the same  *
- * set of rules here, creating our own API symbol names.                *
- ************************************************************************/
-
-#  if defined(PY_ARRAY_UNIQUE_SYMBOL)
-#    define XBOB_IO_MAKE_API_NAME_INNER(a) XBOB_IO_ ## a
-#    define XBOB_IO_MAKE_API_NAME(a) XBOB_IO_MAKE_API_NAME_INNER(a)
-#    define PyXbobIo_API XBOB_IO_MAKE_API_NAME(PY_ARRAY_UNIQUE_SYMBOL)
-#  endif
-
 #  if defined(NO_IMPORT_ARRAY)
   extern void **PyXbobIo_API;
 #  else
diff --git a/xbob/io/videoreader.cpp b/xbob/io/videoreader.cpp
index 8f4063b1375c49f5094d64dabbc8aba2ef08e091..b6a92c585a522d8686ee3c22372e3f8fa5b17e82 100644
--- a/xbob/io/videoreader.cpp
+++ b/xbob/io/videoreader.cpp
@@ -353,6 +353,7 @@ static PyObject* PyBobIoVideoReader_Load(PyBobIoVideoReaderObject* self, PyObjec
 
   PyObject* retval = PyArray_SimpleNew(info.nd, shape, type_num);
   if (!retval) return 0;
+  auto retval_ = make_safe(retval);
 
   Py_ssize_t frames_read = 0;
 
@@ -362,12 +363,10 @@ static PyObject* PyBobIoVideoReader_Load(PyBobIoVideoReaderObject* self, PyObjec
   }
   catch (std::exception& e) {
     if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError, e.what());
-    Py_DECREF(retval);
     return 0;
   }
   catch (...) {
     if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught unknown exception while reading video from file `%s'", self->v->filename().c_str());
-    Py_DECREF(retval);
     return 0;
   }
 
@@ -380,6 +379,7 @@ static PyObject* PyBobIoVideoReader_Load(PyBobIoVideoReaderObject* self, PyObjec
     PyArray_Resize((PyArrayObject*)retval, &newshape, 1, NPY_ANYORDER);
   }
 
+  Py_INCREF(retval);
   return retval;
 
 }
@@ -432,6 +432,7 @@ static PyObject* PyBobIoVideoReader_GetIndex (PyBobIoVideoReaderObject* self, Py
 
   PyObject* retval = PyArray_SimpleNew(info.nd, shape, type_num);
   if (!retval) return 0;
+  auto retval_ = make_safe(retval);
 
   try {
     auto it = self->v->begin();
@@ -441,15 +442,14 @@ static PyObject* PyBobIoVideoReader_GetIndex (PyBobIoVideoReaderObject* self, Py
   }
   catch (std::exception& e) {
     if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError, e.what());
-    Py_DECREF(retval);
     return 0;
   }
   catch (...) {
     if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught unknown exception while reading frame #%" PY_FORMAT_SIZE_T "d from file `%s'", i, self->v->filename().c_str());
-    Py_DECREF(retval);
     return 0;
   }
 
+  Py_INCREF(retval);
   return retval;
 
 }
@@ -478,6 +478,7 @@ static PyObject* PyBobIoVideoReader_GetSlice (PyBobIoVideoReaderObject* self, Py
 
   PyObject* retval = PyArray_SimpleNew(info.nd+1, shape, type_num);
   if (!retval) return 0;
+  auto retval_ = make_safe(retval);
 
   Py_ssize_t counter;
   Py_ssize_t lo, hi, st;
@@ -496,17 +497,12 @@ static PyObject* PyBobIoVideoReader_GetSlice (PyBobIoVideoReaderObject* self, Py
     //get slice to fill
     PyObject* islice = Py_BuildValue("n", counter);
     counter = (st == -step)? counter-1 : counter+1;
-    if (!islice) {
-      Py_DECREF(retval);
-      return 0;
-    }
+    if (!islice) return 0;
+    auto islice_ = make_safe(islice);
 
     PyObject* item = PyObject_GetItem(retval, islice);
-    Py_DECREF(islice);
-    if (!item) {
-      Py_DECREF(retval);
-      return 0;
-    }
+    if (!item) return 0;
+    auto item_ = make_safe(item);
 
     try {
       bobskin skin((PyArrayObject*)item, info.dtype);
@@ -515,19 +511,16 @@ static PyObject* PyBobIoVideoReader_GetSlice (PyBobIoVideoReaderObject* self, Py
     }
     catch (std::exception& e) {
       if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError, e.what());
-      Py_DECREF(retval);
-      Py_DECREF(item);
       return 0;
     }
     catch (...) {
       if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught unknown exception while reading frame #%" PY_FORMAT_SIZE_T "d from file `%s'", i, self->v->filename().c_str());
-      Py_DECREF(retval);
-      Py_DECREF(item);
       return 0;
     }
 
   }
 
+  Py_INCREF(retval);
   return retval;
 
 }
@@ -596,6 +589,7 @@ static PyObject* PyBobIoVideoReaderIterator_Next (PyBobIoVideoReaderIteratorObje
 
   PyObject* retval = PyArray_SimpleNew(info.nd, shape, type_num);
   if (!retval) return 0;
+  auto retval_ = make_safe(retval);
 
   try {
     bobskin skin((PyArrayObject*)retval, info.dtype);
@@ -603,15 +597,14 @@ static PyObject* PyBobIoVideoReaderIterator_Next (PyBobIoVideoReaderIteratorObje
   }
   catch (std::exception& e) {
     if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError, e.what());
-    Py_DECREF(retval);
     return 0;
   }
   catch (...) {
     if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught unknown exception while reading frame #%" PY_FORMAT_SIZE_T "d from file `%s'", self->iter->cur(), self->pyreader->v->filename().c_str());
-    Py_DECREF(retval);
     return 0;
   }
 
+  Py_INCREF(retval);
   return retval;
 
 }
diff --git a/xbob/io/videowriter.cpp b/xbob/io/videowriter.cpp
index c8ebce249eb987076555f501ce9485dbc43d52e9..7a6d2aeb67d7708b6d829f8c77a09026d27327e8 100644
--- a/xbob/io/videowriter.cpp
+++ b/xbob/io/videowriter.cpp
@@ -419,16 +419,15 @@ static PyObject* PyBobIoVideoWriter_Append(PyBobIoVideoWriterObject* self, PyObj
 
   PyBlitzArrayObject* frame = 0;
   if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kwlist, &PyBlitzArray_BehavedConverter, &frame)) return 0;
+  auto frame_ = make_safe(frame);
 
   if (frame->ndim != 3 && frame->ndim != 4) {
     PyErr_Format(PyExc_ValueError, "input array should have 3 or 4 dimensions, but you passed an array with %" PY_FORMAT_SIZE_T "d dimensions", frame->ndim);
-    Py_DECREF(frame);
     return 0;
   }
 
   if (frame->type_num != NPY_UINT8) {
     PyErr_Format(PyExc_TypeError, "input array should have dtype `uint8', but you passed an array with dtype == `%s'", PyBlitzArray_TypenumAsString(frame->type_num));
-    Py_DECREF(frame);
     return 0;
   }
 
@@ -442,16 +441,13 @@ static PyObject* PyBobIoVideoWriter_Append(PyBobIoVideoWriterObject* self, PyObj
   }
   catch (std::exception& e) {
     if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError, e.what());
-    Py_DECREF(frame);
     return 0;
   }
   catch (...) {
     if (!PyErr_Occurred()) PyErr_Format(PyExc_RuntimeError, "caught unknown exception while writing frame #%" PY_FORMAT_SIZE_T "d to file `%s'", self->v->numberOfFrames(), self->v->filename().c_str());
-    Py_DECREF(frame);
     return 0;
   }
 
-  Py_DECREF(frame);
   Py_RETURN_NONE;
 
 }