diff --git a/bindings/pyroot_experimental/PyROOT/CMakeLists.txt b/bindings/pyroot_experimental/PyROOT/CMakeLists.txt
index 891f3027ba4d46fee66adc3e67220528cbe5af7f..556e2f1bce1d67bb14cf36523e2cdb89eceec7bc 100644
--- a/bindings/pyroot_experimental/PyROOT/CMakeLists.txt
+++ b/bindings/pyroot_experimental/PyROOT/CMakeLists.txt
@@ -26,14 +26,15 @@ set(sources
   src/PyROOTModule.cxx
   src/PyROOTStrings.cxx
   src/PyROOTWrapper.cxx
+  src/GenericPyz.cxx
+  src/RVecPyz.cxx
+  src/TClassPyz.cxx
+  src/TClonesArrayPyz.cxx
   src/TDirectoryPyz.cxx
   src/TFilePyz.cxx
   src/TTreePyz.cxx
-  src/TClonesArrayPyz.cxx
-  src/GenericPyz.cxx
-  src/RVecPyz.cxx
-  src/PyzPythonHelpers.cxx
   src/PyzCppHelpers.cxx
+  src/PyzPythonHelpers.cxx
 )
 
 file(COPY python/ROOT DESTINATION ${localruntimedir})
diff --git a/bindings/pyroot_experimental/PyROOT/python/ROOT/pythonization/_tclass.py b/bindings/pyroot_experimental/PyROOT/python/ROOT/pythonization/_tclass.py
new file mode 100644
index 0000000000000000000000000000000000000000..7f716689b410505ad91f25c4b3ead7b7fbe8a6ff
--- /dev/null
+++ b/bindings/pyroot_experimental/PyROOT/python/ROOT/pythonization/_tclass.py
@@ -0,0 +1,23 @@
+# Author: Enric Tejedor CERN  02/2019
+
+################################################################################
+# Copyright (C) 1995-2019, Rene Brun and Fons Rademakers.                      #
+# All rights reserved.                                                         #
+#                                                                              #
+# For the licensing terms see $ROOTSYS/LICENSE.                                #
+# For the list of contributors see $ROOTSYS/README/CREDITS.                    #
+################################################################################
+
+from ROOT import pythonization
+import cppyy
+from libROOTPython import AddTClassDynamicCastPyz
+
+
+@pythonization(lazy = False)
+def pythonize_tclass():
+    klass = cppyy.gbl.TClass
+
+    # DynamicCast
+    AddTClassDynamicCastPyz(klass)
+
+    return True
diff --git a/bindings/pyroot_experimental/PyROOT/src/PyROOTModule.cxx b/bindings/pyroot_experimental/PyROOT/src/PyROOTModule.cxx
index 141722ac7593adbb50f07a492a9416350cd78ded..060fbdc1108322f8054d666d4bdb3acea289d7b1 100644
--- a/bindings/pyroot_experimental/PyROOT/src/PyROOTModule.cxx
+++ b/bindings/pyroot_experimental/PyROOT/src/PyROOTModule.cxx
@@ -45,6 +45,8 @@ static PyMethodDef gPyROOTMethods[] = {{(char *)"AddDirectoryWritePyz", (PyCFunc
                                         (char *)"Allow to access branches as tree attributes"},
                                        {(char *)"AddFileOpenPyz", (PyCFunction)PyROOT::AddFileOpenPyz, METH_VARARGS,
                                         (char *)"Make TFile::Open a constructor, adjusting for example the reference count"},
+                                        {(char *)"AddTClassDynamicCastPyz", (PyCFunction)PyROOT::AddTClassDynamicCastPyz, METH_VARARGS,
+                                        (char *)"Cast the void* returned by TClass::DynamicCast to the right type"},
                                        {(char *)"SetBranchAddressPyz", (PyCFunction)PyROOT::SetBranchAddressPyz, METH_VARARGS,
                                         (char *)"Fully enable the use of TTree::SetBranchAddress from Python"},
                                        {(char *)"BranchPyz", (PyCFunction)PyROOT::BranchPyz, METH_VARARGS,
diff --git a/bindings/pyroot_experimental/PyROOT/src/PyROOTPythonize.h b/bindings/pyroot_experimental/PyROOT/src/PyROOTPythonize.h
index ec7761a51ade461bf7825cde004eb2eea5a68e4d..344881370c3ef0203623bfd50124ab937fb536c4 100644
--- a/bindings/pyroot_experimental/PyROOT/src/PyROOTPythonize.h
+++ b/bindings/pyroot_experimental/PyROOT/src/PyROOTPythonize.h
@@ -17,17 +17,24 @@
 namespace PyROOT {
 
 PyObject *AddPrettyPrintingPyz(PyObject *self, PyObject *args);
-PyObject *AddDirectoryWritePyz(PyObject *self, PyObject *args);
+
 PyObject *AddDirectoryAttrSyntaxPyz(PyObject *self, PyObject *args);
-PyObject *AddBranchAttrSyntax(PyObject *self, PyObject *args);
+PyObject *AddDirectoryWritePyz(PyObject *self, PyObject *args);
 PyObject *AddFileOpenPyz(PyObject *self, PyObject *args);
-PyObject *AddSetItemTCAPyz(PyObject *self, PyObject *args);
-PyObject *SetBranchAddressPyz(PyObject *self, PyObject *args);
+
+PyObject *AddBranchAttrSyntax(PyObject *self, PyObject *args);
 PyObject *BranchPyz(PyObject *self, PyObject *args);
+PyObject *SetBranchAddressPyz(PyObject *self, PyObject *args);
+
+PyObject *AddTClassDynamicCastPyz(PyObject *self, PyObject *args);
+
+PyObject *AddSetItemTCAPyz(PyObject *self, PyObject *args);
+
+PyObject *AsRVec(PyObject *self, PyObject *obj);
+
 PyObject *GetEndianess(PyObject *self);
 PyObject *GetVectorDataPointer(PyObject *self, PyObject *args);
 PyObject *GetSizeOfType(PyObject *self, PyObject *args);
-PyObject *AsRVec(PyObject *self, PyObject *obj);
 
 } // namespace PyROOT
 
diff --git a/bindings/pyroot_experimental/PyROOT/src/TClassPyz.cxx b/bindings/pyroot_experimental/PyROOT/src/TClassPyz.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..886522e47d8c0808abe77d546e1a8b656ee82ce1
--- /dev/null
+++ b/bindings/pyroot_experimental/PyROOT/src/TClassPyz.cxx
@@ -0,0 +1,95 @@
+// Author: Enric Tejedor CERN  02/2019
+// Original PyROOT code by Wim Lavrijsen, LBL
+
+/*************************************************************************
+ * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+// Bindings
+#include "CPyCppyy.h"
+#include "PyROOTPythonize.h"
+#include "PyROOTStrings.h"
+#include "CPPInstance.h"
+#include "Utility.h"
+#include "ProxyWrappers.h"
+#include "PyzCppHelpers.hxx"
+
+// ROOT
+#include "TClass.h"
+
+using namespace CPyCppyy;
+
+// Cast the void* returned by TClass::DynamicCast to the right type
+PyObject *TClassDynamicCastPyz(CPPInstance *self, PyObject *args)
+{
+   // Parse arguments
+   CPPInstance *pyclass = nullptr;
+   PyObject *pyobject = nullptr;
+   int up = 1;
+   if (!PyArg_ParseTuple(args, const_cast<char *>("O!O|i:DynamicCast"),
+                         &CPPInstance_Type, &pyclass,
+                         &pyobject,
+                         &up))
+      return nullptr;
+
+   // Perform actual cast - calls default implementation of DynamicCast
+   auto meth = PyObject_GetAttr((PyObject *)self, PyROOT::PyStrings::gTClassDynCast);
+   auto ptr = meth ? PyObject_Call(meth, args, nullptr) : nullptr;
+   Py_XDECREF(meth);
+
+   // Simply forward in case of call failure
+   if (!ptr)
+      return nullptr;
+
+   // Retrieve object address
+   void *address = nullptr;
+   if (CPPInstance_Check(pyobject)) {
+      address = ((CPPInstance *)pyobject)->GetObject();
+   } else if (PyInt_Check(pyobject) || PyLong_Check(pyobject)) {
+      address = (void *)PyLong_AsLong(pyobject);
+   } else {
+      Utility::GetBuffer(pyobject, '*', 1, address, false);
+   }
+
+   if (PyErr_Occurred()) {
+      // Error getting object address, just return the void* wrapper
+      PyErr_Clear();
+      return ptr;
+   }
+
+   // Now use binding to return a usable class
+   TClass *klass = nullptr;
+   if (up) {
+      // Upcast: result is a base
+      klass = (TClass *)GetTClass(pyclass)->DynamicCast(TClass::Class(), pyclass->GetObject());
+   } else {
+      // Downcast: result is a derived
+      klass = (TClass *)GetTClass(self)->DynamicCast(TClass::Class(), self->GetObject());
+   }
+
+   PyObject *result = BindCppObjectNoCast(address, Cppyy::GetScope(klass->GetName()));
+   Py_DECREF(ptr);
+
+   return result;
+}
+
+////////////////////////////////////////////////////////////////////////////
+/// \brief Add pythonization for TClass::DynamicCast.
+/// \param[in] self Always null, since this is a module function.
+/// \param[in] args Pointer to a Python tuple object containing the arguments
+/// received from Python.
+///
+/// TClass::DynamicCast returns a void* that the user still has to cast (it
+/// will have the proper offset, though). Fix this by providing the requested
+/// binding if the cast succeeded.
+PyObject *PyROOT::AddTClassDynamicCastPyz(PyObject * /* self */, PyObject *args)
+{
+   PyObject *pyclass = PyTuple_GetItem(args, 0);
+   Utility::AddToClass(pyclass, "_TClass__DynamicCast", "DynamicCast");
+   Utility::AddToClass(pyclass, "DynamicCast", (PyCFunction)TClassDynamicCastPyz);
+   Py_RETURN_NONE;
+}
\ No newline at end of file