Issue #13053: Added section on migrating from CObject to Capsule
to howto/cporting.rst.
diff --git a/Doc/howto/cporting.rst b/Doc/howto/cporting.rst
index 46482ab..5ba5df7 100644
--- a/Doc/howto/cporting.rst
+++ b/Doc/howto/cporting.rst
@@ -209,6 +209,58 @@
    }
 
 
+CObject replaced with Capsule
+=============================
+
+The :ctype:`Capsule` object was introduced in Python 3.1 and 2.7 to replace
+:ctype:`CObject`.  CObjects were useful,
+but the :ctype:`CObject` API was problematic: it didn't permit distinguishing
+between valid CObjects, which allowed mismatched CObjects to crash the
+interpreter, and some of its APIs relied on undefined behavior in C.
+(For further reading on the rationale behind Capsules, please see :issue:`5630`.)
+
+If you're currently using CObjects, and you want to migrate to 3.1 or newer,
+you'll need to switch to Capsules.
+:ctype:`CObject` was deprecated in 3.1 and 2.7 and completely removed in
+Python 3.2.  If you only support 2.7, or 3.1 and above, you
+can simply switch to :ctype:`Capsule`.  If you need to support 3.0 or
+versions of Python earlier than 2.7 you'll have to support both CObjects
+and Capsules.
+
+The following example header file :file:`capsulethunk.h` may
+solve the problem for you;
+simply write your code against the :ctype:`Capsule` API, include
+this header file after ``"Python.h"``, and you'll automatically use CObjects
+in Python 3.0 or versions earlier than 2.7.
+
+:file:`capsulethunk.h` simulates Capsules using CObjects.  However,
+:ctype:`CObject` provides no place to store the capsule's "name".  As a
+result the simulated :ctype:`Capsule` objects created by :file:`capsulethunk.h`
+behave slightly differently from real Capsules.  Specifically:
+
+  * The name parameter passed in to :cfunc:`PyCapsule_New` is ignored.
+
+  * The name parameter passed in to :cfunc:`PyCapsule_IsValid` and
+    :cfunc:`PyCapsule_GetPointer` is ignored, and no error checking
+    of the name is performed.
+
+  * :cfunc:`PyCapsule_GetName` always returns NULL.
+
+  * :cfunc:`PyCapsule_SetName` always throws an exception and
+    returns failure.  (Since there's no way to store a name
+    in a CObject, noisy failure of :cfunc:`PyCapsule_SetName`
+    was deemed preferable to silent failure here.  If this is
+    inconveient, feel free to modify your local
+    copy as you see fit.)
+
+You can find :file:`capsulethunk.h` in the Python source distribution
+in the :file:`Doc/includes` directory.  We also include it here for
+your reference; here is :file:`capsulethunk.h`:
+
+.. literalinclude:: ../includes/capsulethunk.h
+
+
+
 Other options
 =============
 
diff --git a/Doc/includes/capsulethunk.h b/Doc/includes/capsulethunk.h
new file mode 100644
index 0000000..6b20564
--- /dev/null
+++ b/Doc/includes/capsulethunk.h
@@ -0,0 +1,134 @@
+#ifndef __CAPSULETHUNK_H
+#define __CAPSULETHUNK_H
+
+#if (    (PY_VERSION_HEX <  0x02070000) \
+     || ((PY_VERSION_HEX >= 0x03000000) \
+      && (PY_VERSION_HEX <  0x03010000)) )
+
+#define __PyCapsule_GetField(capsule, field, default_value) \
+    ( PyCapsule_CheckExact(capsule) \
+        ? (((PyCObject *)capsule)->field) \
+        : (default_value) \
+    ) \
+
+#define __PyCapsule_SetField(capsule, field, value) \
+    ( PyCapsule_CheckExact(capsule) \
+        ? (((PyCObject *)capsule)->field = value), 1 \
+        : 0 \
+    ) \
+
+
+#define PyCapsule_Type PyCObject_Type
+
+#define PyCapsule_CheckExact(capsule) (PyCObject_Check(capsule))
+#define PyCapsule_IsValid(capsule, name) (PyCObject_Check(capsule))
+
+
+#define PyCapsule_New(pointer, name, destructor) \
+    (PyCObject_FromVoidPtr(pointer, destructor))
+
+
+#define PyCapsule_GetPointer(capsule, name) \
+    (PyCObject_AsVoidPtr(capsule))
+
+/* Don't call PyCObject_SetPointer here, it fails if there's a destructor */
+#define PyCapsule_SetPointer(capsule, pointer) \
+    __PyCapsule_SetField(capsule, cobject, pointer)
+
+
+#define PyCapsule_GetDestructor(capsule) \
+    __PyCapsule_GetField(capsule, destructor)
+
+#define PyCapsule_SetDestructor(capsule, dtor) \
+    __PyCapsule_SetField(capsule, destructor, dtor)
+
+
+/*
+ * Sorry, there's simply no place
+ * to store a Capsule "name" in a CObject.
+ */
+#define PyCapsule_GetName(capsule) NULL
+
+static int
+PyCapsule_SetName(PyObject *capsule, const char *unused)
+{
+    unused = unused;
+    PyErr_SetString(PyExc_NotImplementedError,
+        "can't use PyCapsule_SetName with CObjects");
+    return 1;
+}
+
+
+
+#define PyCapsule_GetContext(capsule) \
+    __PyCapsule_GetField(capsule, descr)
+
+#define PyCapsule_SetContext(capsule, context) \
+    __PyCapsule_SetField(capsule, descr, context)
+
+
+static void *
+PyCapsule_Import(const char *name, int no_block)
+{
+    PyObject *object = NULL;
+    void *return_value = NULL;
+    char *trace;
+    size_t name_length = (strlen(name) + 1) * sizeof(char);
+    char *name_dup = (char *)PyMem_MALLOC(name_length);
+
+    if (!name_dup) {
+        return NULL;
+    }
+
+    memcpy(name_dup, name, name_length);
+
+    trace = name_dup;
+    while (trace) {
+        char *dot = strchr(trace, '.');
+        if (dot) {
+            *dot++ = '\0';
+        }
+
+        if (object == NULL) {
+            if (no_block) {
+                object = PyImport_ImportModuleNoBlock(trace);
+            } else {
+                object = PyImport_ImportModule(trace);
+                if (!object) {
+                    PyErr_Format(PyExc_ImportError,
+                        "PyCapsule_Import could not "
+                        "import module \"%s\"", trace);
+                }
+            }
+        } else {
+            PyObject *object2 = PyObject_GetAttrString(object, trace);
+            Py_DECREF(object);
+            object = object2;
+        }
+        if (!object) {
+            goto EXIT;
+        }
+
+        trace = dot;
+    }
+
+    if (PyCObject_Check(object)) {
+        PyCObject *cobject = (PyCObject *)object;
+        return_value = cobject->cobject;
+    } else {
+        PyErr_Format(PyExc_AttributeError,
+            "PyCapsule_Import \"%s\" is not valid",
+            name);
+    }
+
+EXIT:
+    Py_XDECREF(object);
+    if (name_dup) {
+        PyMem_FREE(name_dup);
+    }
+    return return_value;
+}
+
+#endif /* #if PY_VERSION_HEX < 0x02070000 */
+
+#endif /* __CAPSULETHUNK_H */