[Python-checkins] r79397 - in python/trunk: Doc/c-api/capsule.rst Doc/c-api/cobject.rst Doc/c-api/concrete.rst Doc/data/refcounts.dat Doc/extending/extending.rst Include/Python.h Include/cStringIO.h Include/cobject.h Include/datetime.h Include/py_curses.h Include/pycapsule.h Include/pyexpat.h Include/ucnhash.h Lib/test/test_sys.py Makefile.pre.in Misc/NEWS Modules/_ctypes/callproc.c Modules/_ctypes/cfield.c Modules/_ctypes/ctypes.h Modules/_cursesmodule.c Modules/_elementtree.c Modules/_testcapimodule.c Modules/cStringIO.c Modules/cjkcodecs/cjkcodecs.h Modules/cjkcodecs/multibytecodec.c Modules/cjkcodecs/multibytecodec.h Modules/datetimemodule.c Modules/pyexpat.c Modules/socketmodule.c Modules/socketmodule.h Modules/unicodedata.c Objects/capsule.c Objects/object.c Objects/unicodeobject.c PC/VS7.1/pythoncore.vcproj PC/VS8.0/pythoncore.vcproj PC/os2emx/python27.def PC/os2vacpp/python.def Python/compile.c Python/getargs.c

larry.hastings python-checkins at python.org
Thu Mar 25 01:54:54 CET 2010


Author: larry.hastings
Date: Thu Mar 25 01:54:54 2010
New Revision: 79397

Log:
Backported PyCapsule from 3.1, and converted most uses of
CObject to PyCapsule.



Added:
   python/trunk/Doc/c-api/capsule.rst
   python/trunk/Include/pycapsule.h
   python/trunk/Objects/capsule.c
Modified:
   python/trunk/Doc/c-api/cobject.rst
   python/trunk/Doc/c-api/concrete.rst
   python/trunk/Doc/data/refcounts.dat
   python/trunk/Doc/extending/extending.rst
   python/trunk/Include/Python.h
   python/trunk/Include/cStringIO.h
   python/trunk/Include/cobject.h
   python/trunk/Include/datetime.h
   python/trunk/Include/py_curses.h
   python/trunk/Include/pyexpat.h
   python/trunk/Include/ucnhash.h
   python/trunk/Lib/test/test_sys.py
   python/trunk/Makefile.pre.in
   python/trunk/Misc/NEWS
   python/trunk/Modules/_ctypes/callproc.c
   python/trunk/Modules/_ctypes/cfield.c
   python/trunk/Modules/_ctypes/ctypes.h
   python/trunk/Modules/_cursesmodule.c
   python/trunk/Modules/_elementtree.c
   python/trunk/Modules/_testcapimodule.c
   python/trunk/Modules/cStringIO.c
   python/trunk/Modules/cjkcodecs/cjkcodecs.h
   python/trunk/Modules/cjkcodecs/multibytecodec.c
   python/trunk/Modules/cjkcodecs/multibytecodec.h
   python/trunk/Modules/datetimemodule.c
   python/trunk/Modules/pyexpat.c
   python/trunk/Modules/socketmodule.c
   python/trunk/Modules/socketmodule.h
   python/trunk/Modules/unicodedata.c
   python/trunk/Objects/object.c
   python/trunk/Objects/unicodeobject.c
   python/trunk/PC/VS7.1/pythoncore.vcproj
   python/trunk/PC/VS8.0/pythoncore.vcproj
   python/trunk/PC/os2emx/python27.def
   python/trunk/PC/os2vacpp/python.def
   python/trunk/Python/compile.c
   python/trunk/Python/getargs.c

Added: python/trunk/Doc/c-api/capsule.rst
==============================================================================
--- (empty file)
+++ python/trunk/Doc/c-api/capsule.rst	Thu Mar 25 01:54:54 2010
@@ -0,0 +1,150 @@
+.. highlightlang:: c
+
+.. _capsules:
+
+Capsules
+--------
+
+.. index:: object: Capsule
+
+Refer to :ref:`using-capsules` for more information on using these objects.
+
+
+.. ctype:: PyCapsule
+
+   This subtype of :ctype:`PyObject` represents an opaque value, useful for C
+   extension modules who need to pass an opaque value (as a :ctype:`void\*`
+   pointer) through Python code to other C code.  It is often used to make a C
+   function pointer defined in one module available to other modules, so the
+   regular import mechanism can be used to access C APIs defined in dynamically
+   loaded modules.
+
+.. ctype:: PyCapsule_Destructor
+
+   The type of a destructor callback for a capsule.  Defined as::
+
+      typedef void (*PyCapsule_Destructor)(PyObject *);
+
+   See :cfunc:`PyCapsule_New` for the semantics of PyCapsule_Destructor
+   callbacks.
+
+
+.. cfunction:: int PyCapsule_CheckExact(PyObject *p)
+
+   Return true if its argument is a :ctype:`PyCapsule`.
+
+
+.. cfunction:: PyObject* PyCapsule_New(void *pointer, const char *name, PyCapsule_Destructor destructor)
+
+   Create a :ctype:`PyCapsule` encapsulating the *pointer*.  The *pointer*
+   argument may not be *NULL*.
+
+   On failure, set an exception and return *NULL*.
+
+   The *name* string may either be *NULL* or a pointer to a valid C string.  If
+   non-*NULL*, this string must outlive the capsule.  (Though it is permitted to
+   free it inside the *destructor*.)
+
+   If the *destructor* argument is not *NULL*, it will be called with the
+   capsule as its argument when it is destroyed.
+
+   If this capsule will be stored as an attribute of a module, the *name* should
+   be specified as ``modulename.attributename``.  This will enable other modules
+   to import the capsule using :cfunc:`PyCapsule_Import`.
+
+
+.. cfunction:: void* PyCapsule_GetPointer(PyObject *capsule, const char *name)
+
+   Retrieve the *pointer* stored in the capsule.  On failure, set an exception
+   and return *NULL*.
+
+   The *name* parameter must compare exactly to the name stored in the capsule.
+   If the name stored in the capsule is *NULL*, the *name* passed in must also
+   be *NULL*.  Python uses the C function :cfunc:`strcmp` to compare capsule
+   names.
+
+
+.. cfunction:: PyCapsule_Destructor PyCapsule_GetDestructor(PyObject *capsule)
+
+   Return the current destructor stored in the capsule.  On failure, set an
+   exception and return *NULL*.
+
+   It is legal for a capsule to have a *NULL* destructor.  This makes a *NULL*
+   return code somewhat ambiguous; use :cfunc:`PyCapsule_IsValid` or
+   :cfunc:`PyErr_Occurred` to disambiguate.
+
+
+.. cfunction:: void* PyCapsule_GetContext(PyObject *capsule)
+
+   Return the current context stored in the capsule.  On failure, set an
+   exception and return *NULL*.
+
+   It is legal for a capsule to have a *NULL* context.  This makes a *NULL*
+   return code somewhat ambiguous; use :cfunc:`PyCapsule_IsValid` or
+   :cfunc:`PyErr_Occurred` to disambiguate.
+
+
+.. cfunction:: const char* PyCapsule_GetName(PyObject *capsule)
+
+   Return the current name stored in the capsule.  On failure, set an exception
+   and return *NULL*.
+
+   It is legal for a capsule to have a *NULL* name.  This makes a *NULL* return
+   code somewhat ambiguous; use :cfunc:`PyCapsule_IsValid` or
+   :cfunc:`PyErr_Occurred` to disambiguate.
+
+
+.. cfunction:: void* PyCapsule_Import(const char *name, int no_block)
+
+   Import a pointer to a C object from a capsule attribute in a module.  The
+   *name* parameter should specify the full name to the attribute, as in
+   ``module.attribute``.  The *name* stored in the capsule must match this
+   string exactly.  If *no_block* is true, import the module without blocking
+   (using :cfunc:`PyImport_ImportModuleNoBlock`).  If *no_block* is false,
+   import the module conventionally (using :cfunc:`PyImport_ImportModule`).
+
+   Return the capsule's internal *pointer* on success.  On failure, set an
+   exception and return *NULL*.  However, if :cfunc:`PyCapsule_Import` failed to
+   import the module, and *no_block* was true, no exception is set.
+
+.. cfunction:: int PyCapsule_IsValid(PyObject *capsule, const char *name)
+
+   Determines whether or not *capsule* is a valid capsule.  A valid capsule is
+   non-*NULL*, passes :cfunc:`PyCapsule_CheckExact`, has a non-*NULL* pointer
+   stored in it, and its internal name matches the *name* parameter.  (See
+   :cfunc:`PyCapsule_GetPointer` for information on how capsule names are
+   compared.)
+
+   In other words, if :cfunc:`PyCapsule_IsValid` returns a true value, calls to
+   any of the accessors (any function starting with :cfunc:`PyCapsule_Get`) are
+   guaranteed to succeed.
+
+   Return a nonzero value if the object is valid and matches the name passed in.
+   Return 0 otherwise.  This function will not fail.
+
+.. cfunction:: int PyCapsule_SetContext(PyObject *capsule, void *context)
+
+   Set the context pointer inside *capsule* to *context*.
+
+   Return 0 on success.  Return nonzero and set an exception on failure.
+
+.. cfunction:: int PyCapsule_SetDestructor(PyObject *capsule, PyCapsule_Destructor destructor)
+
+   Set the destructor inside *capsule* to *destructor*.
+
+   Return 0 on success.  Return nonzero and set an exception on failure.
+
+.. cfunction:: int PyCapsule_SetName(PyObject *capsule, const char *name)
+
+   Set the name inside *capsule* to *name*.  If non-*NULL*, the name must
+   outlive the capsule.  If the previous *name* stored in the capsule was not
+   *NULL*, no attempt is made to free it.
+
+   Return 0 on success.  Return nonzero and set an exception on failure.
+
+.. cfunction:: int PyCapsule_SetPointer(PyObject *capsule, void *pointer)
+
+   Set the void pointer inside *capsule* to *pointer*.  The pointer may not be
+   *NULL*.
+
+   Return 0 on success.  Return nonzero and set an exception on failure.

Modified: python/trunk/Doc/c-api/cobject.rst
==============================================================================
--- python/trunk/Doc/c-api/cobject.rst	(original)
+++ python/trunk/Doc/c-api/cobject.rst	Thu Mar 25 01:54:54 2010
@@ -7,8 +7,11 @@
 
 .. index:: object: CObject
 
-Refer to :ref:`using-cobjects` for more information on using these objects.
 
+.. warning::
+
+   The CObject API is deprecated as of Python 2.7.  Please switch to the new
+   :ref:`capsules` API.
 
 .. ctype:: PyCObject
 

Modified: python/trunk/Doc/c-api/concrete.rst
==============================================================================
--- python/trunk/Doc/c-api/concrete.rst	(original)
+++ python/trunk/Doc/c-api/concrete.rst	Thu Mar 25 01:54:54 2010
@@ -100,6 +100,7 @@
    descriptor.rst
    slice.rst
    weakref.rst
+   capsule.rst
    cobject.rst
    cell.rst
    gen.rst

Modified: python/trunk/Doc/data/refcounts.dat
==============================================================================
--- python/trunk/Doc/data/refcounts.dat	(original)
+++ python/trunk/Doc/data/refcounts.dat	Thu Mar 25 01:54:54 2010
@@ -55,6 +55,45 @@
 PyBuffer_New:PyObject*::+1:
 PyBuffer_New:int:size::
 
+PyCapsule_GetContext:void *:::
+PyCapsule_GetContext:PyObject*:self:0:
+
+PyCapsule_GetDestructor:void (*)(PyObject *):::
+PyCapsule_GetDestructor:PyObject*:self:0:
+
+PyCapsule_GetName:const char *:::
+PyCapsule_GetName:PyObject*:self:0:
+
+PyCapsule_GetPointer:void*:::
+PyCapsule_GetPointer:PyObject*:self:0:
+PyCapsule_GetPointer:const char *:name::
+
+PyCapsule_Import:void *:::
+PyCapsule_Import:const char *:name::
+PyCapsule_Import:int:no_block::
+
+PyCapsule_New:PyObject*::+1:
+PyCapsule_New:void*:pointer::
+PyCapsule_New:const char *:name::
+PyCapsule_New::void (* destructor)(PyObject* )::
+
+PyCapsule_SetContext:int:::
+PyCapsule_SetContext:PyObject*:self:0:
+PyCapsule_SetContext:void *:context::
+
+PyCapsule_SetDestructor:int:::
+PyCapsule_SetDestructor:PyObject*:self:0:
+PyCapsule_SetDestructor:void (*)(PyObject *):destructor::
+
+PyCapsule_SetName:int:::
+PyCapsule_SetName:PyObject*:self:0:
+PyCapsule_SetName:const char *:name::
+
+PyCapsule_SetPointer:int:::
+PyCapsule_SetPointer:PyObject*:self:0:
+PyCapsule_SetPointer:void*:pointer::
+
+
 PyCObject_AsVoidPtr:void*:::
 PyCObject_AsVoidPtr:PyObject*:self:0:
 

Modified: python/trunk/Doc/extending/extending.rst
==============================================================================
--- python/trunk/Doc/extending/extending.rst	(original)
+++ python/trunk/Doc/extending/extending.rst	Thu Mar 25 01:54:54 2010
@@ -1060,7 +1060,7 @@
 define this symbol).
 
 
-.. _using-cobjects:
+.. _using-capsules:
 
 Providing a C API for an Extension Module
 =========================================
@@ -1096,23 +1096,40 @@
 other extension modules must be exported in a different way.
 
 Python provides a special mechanism to pass C-level information (pointers) from
-one extension module to another one: CObjects. A CObject is a Python data type
-which stores a pointer (:ctype:`void \*`).  CObjects can only be created and
+one extension module to another one: Capsules. A Capsule is a Python data type
+which stores a pointer (:ctype:`void \*`).  Capsules can only be created and
 accessed via their C API, but they can be passed around like any other Python
 object. In particular,  they can be assigned to a name in an extension module's
 namespace. Other extension modules can then import this module, retrieve the
-value of this name, and then retrieve the pointer from the CObject.
+value of this name, and then retrieve the pointer from the Capsule.
 
-There are many ways in which CObjects can be used to export the C API of an
-extension module. Each name could get its own CObject, or all C API pointers
-could be stored in an array whose address is published in a CObject. And the
+There are many ways in which Capsules can be used to export the C API of an
+extension module. Each function could get its own Capsule, or all C API pointers
+could be stored in an array whose address is published in a Capsule. And the
 various tasks of storing and retrieving the pointers can be distributed in
 different ways between the module providing the code and the client modules.
 
+Whichever method you choose, it's important to name your Capsules properly.
+The function :cfunc:`PyCapsule_New` takes a name parameter
+(:ctype:`const char \*`); you're permitted to pass in a *NULL* name, but
+we strongly encourage you to specify a name.  Properly named Capsules provide
+a degree of runtime type-safety; there is no feasible way to tell one unnamed
+Capsule from another.
+
+In particular, Capsules used to expose C APIs should be given a name following
+this convention::
+
+    modulename.attributename
+
+The convenience function :cfunc:`PyCapsule_Import` makes it easy to
+load a C API provided via a Capsule, but only if the Capsule's name
+matches this convention.  This behavior gives C API users a high degree
+of certainty that the Capsule they load contains the correct C API.
+
 The following example demonstrates an approach that puts most of the burden on
 the writer of the exporting module, which is appropriate for commonly used
 library modules. It stores all C API pointers (just one in the example!) in an
-array of :ctype:`void` pointers which becomes the value of a CObject. The header
+array of :ctype:`void` pointers which becomes the value of a Capsule. The header
 file corresponding to the module provides a macro that takes care of importing
 the module and retrieving its C API pointers; client modules only have to call
 this macro before accessing the C API.
@@ -1174,8 +1191,8 @@
        /* Initialize the C API pointer array */
        PySpam_API[PySpam_System_NUM] = (void *)PySpam_System;
 
-       /* Create a CObject containing the API pointer array's address */
-       c_api_object = PyCObject_FromVoidPtr((void *)PySpam_API, NULL);
+       /* Create a Capsule containing the API pointer array's address */
+       c_api_object = PyCapsule_New((void *)PySpam_API, "spam._C_API", NULL);
 
        if (c_api_object != NULL)
            PyModule_AddObject(m, "_C_API", c_api_object);
@@ -1217,28 +1234,14 @@
    #define PySpam_System \
     (*(PySpam_System_RETURN (*)PySpam_System_PROTO) PySpam_API[PySpam_System_NUM])
 
-   /* Return -1 and set exception on error, 0 on success. */
+   /* Return -1 on error, 0 on success.
+    * PyCapsule_Import will set an exception if there's an error.
+    */
    static int
    import_spam(void)
    {
-       PyObject *c_api_object;
-       PyObject *module;
-
-       module = PyImport_ImportModule("spam");
-       if (module == NULL)
-           return -1;
-
-       c_api_object = PyObject_GetAttrString(module, "_C_API");
-       if (c_api_object == NULL) {
-           Py_DECREF(module);
-           return -1;
-       }
-       if (PyCObject_Check(c_api_object))
-           PySpam_API = (void **)PyCObject_AsVoidPtr(c_api_object);
-
-       Py_DECREF(c_api_object);
-       Py_DECREF(module);
-       return 0;
+       PySpam_API = (void **)PyCapsule_Import("spam._C_API", 0);
+       return (PySpam_API != NULL) ? 0 : -1;
    }
 
    #endif
@@ -1270,11 +1273,11 @@
 rather complicated. However, the basic structure is the same for each function
 that is exported, so it has to be learned only once.
 
-Finally it should be mentioned that CObjects offer additional functionality,
+Finally it should be mentioned that Capsules offer additional functionality,
 which is especially useful for memory allocation and deallocation of the pointer
-stored in a CObject. The details are described in the Python/C API Reference
-Manual in the section :ref:`cobjects` and in the implementation of CObjects (files
-:file:`Include/cobject.h` and :file:`Objects/cobject.c` in the Python source
+stored in a Capsule. The details are described in the Python/C API Reference
+Manual in the section :ref:`capsules` and in the implementation of Capsules (files
+:file:`Include/pycapsule.h` and :file:`Objects/pycapsule.c` in the Python source
 code distribution).
 
 .. rubric:: Footnotes

Modified: python/trunk/Include/Python.h
==============================================================================
--- python/trunk/Include/Python.h	(original)
+++ python/trunk/Include/Python.h	Thu Mar 25 01:54:54 2010
@@ -107,6 +107,7 @@
 #include "classobject.h"
 #include "fileobject.h"
 #include "cobject.h"
+#include "pycapsule.h"
 #include "traceback.h"
 #include "sliceobject.h"
 #include "cellobject.h"

Modified: python/trunk/Include/cStringIO.h
==============================================================================
--- python/trunk/Include/cStringIO.h	(original)
+++ python/trunk/Include/cStringIO.h	Thu Mar 25 01:54:54 2010
@@ -18,9 +18,12 @@
   This would typically be done in your init function.
 
 */
+
+#define PycStringIO_CAPSULE_NAME "cStringIO.cStringIO_CAPI"
+
 #define PycString_IMPORT \
-  PycStringIO = (struct PycStringIO_CAPI*)PyCObject_Import("cStringIO", \
-                                                           "cStringIO_CAPI")
+  PycStringIO = ((struct PycStringIO_CAPI*)PyCapsule_Import(\
+    PycStringIO_CAPSULE_NAME, 0))
 
 /* Basic functions to manipulate cStringIO objects from C */
 

Modified: python/trunk/Include/cobject.h
==============================================================================
--- python/trunk/Include/cobject.h	(original)
+++ python/trunk/Include/cobject.h	Thu Mar 25 01:54:54 2010
@@ -6,6 +6,8 @@
    to other extension modules, so that extension modules can use the
    Python import mechanism to link to one another.
 
+   DEPRECATED - Use PyCapsule objects instead.
+                CObject will be removed in 2.8 (if there is one).
 */
 
 #ifndef Py_COBJECT_H

Modified: python/trunk/Include/datetime.h
==============================================================================
--- python/trunk/Include/datetime.h	(original)
+++ python/trunk/Include/datetime.h	Thu Mar 25 01:54:54 2010
@@ -158,6 +158,8 @@
 
 } PyDateTime_CAPI;
 
+#define PyDateTime_CAPSULE_NAME "datetime.datetime_CAPI"
+
 
 /* "magic" constant used to partially protect against developer mistakes. */
 #define DATETIME_API_MAGIC 0x414548d5
@@ -186,15 +188,7 @@
 static PyDateTime_CAPI *PyDateTimeAPI = NULL;
 
 #define PyDateTime_IMPORT \
-        PyDateTimeAPI = (PyDateTime_CAPI*) PyCObject_Import("datetime", \
-                                                            "datetime_CAPI")
-
-/* This macro would be used if PyCObject_ImportEx() was created.
-#define PyDateTime_IMPORT \
-        PyDateTimeAPI = (PyDateTime_CAPI*) PyCObject_ImportEx("datetime", \
-                                                            "datetime_CAPI", \
-                                                            DATETIME_API_MAGIC)
-*/
+        PyDateTimeAPI = (PyDateTime_CAPI *)PyCapsule_Import(PyDateTime_CAPSULE_NAME, 0)
 
 /* Macros for type checking when not building the Python core. */
 #define PyDate_Check(op) PyObject_TypeCheck(op, PyDateTimeAPI->DateType)

Modified: python/trunk/Include/py_curses.h
==============================================================================
--- python/trunk/Include/py_curses.h	(original)
+++ python/trunk/Include/py_curses.h	Thu Mar 25 01:54:54 2010
@@ -80,6 +80,9 @@
 
 #define PyCursesWindow_Check(v)	 (Py_TYPE(v) == &PyCursesWindow_Type)
 
+#define PyCurses_CAPSULE_NAME "_curses._C_API"
+
+
 #ifdef CURSES_MODULE
 /* This section is used when compiling _cursesmodule.c */
 
@@ -94,16 +97,8 @@
 #define PyCursesInitialisedColor {if (! ((int (*)(void))PyCurses_API[3]) () ) return NULL;}
 
 #define import_curses() \
-{ \
-  PyObject *module = PyImport_ImportModuleNoBlock("_curses"); \
-  if (module != NULL) { \
-    PyObject *module_dict = PyModule_GetDict(module); \
-    PyObject *c_api_object = PyDict_GetItemString(module_dict, "_C_API"); \
-    if (PyCObject_Check(c_api_object)) { \
-      PyCurses_API = (void **)PyCObject_AsVoidPtr(c_api_object); \
-    } \
-  } \
-}
+    PyCurses_API = (void **)PyCapsule_Import(PyCurses_CAPSULE_NAME, 1);
+
 #endif
 
 /* general error messages */

Added: python/trunk/Include/pycapsule.h
==============================================================================
--- (empty file)
+++ python/trunk/Include/pycapsule.h	Thu Mar 25 01:54:54 2010
@@ -0,0 +1,148 @@
+
+/* Capsule objects let you wrap a C "void *" pointer in a Python
+   object.  They're a way of passing data through the Python interpreter
+   without creating your own custom type.
+
+   Capsules are used for communication between extension modules.
+   They provide a way for an extension module to export a C interface
+   to other extension modules, so that extension modules can use the
+   Python import mechanism to link to one another.
+
+   For more information, please see "c-api/capsule.html" in the
+   documentation.
+*/
+
+#ifndef Py_CAPSULE_H
+#define Py_CAPSULE_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+PyAPI_DATA(PyTypeObject) PyCapsule_Type;
+
+typedef void (*PyCapsule_Destructor)(PyObject *);
+
+#define PyCapsule_CheckExact(op) (Py_TYPE(op) == &PyCapsule_Type)
+
+
+PyAPI_FUNC(PyObject *) PyCapsule_New(
+    void *pointer,
+    const char *name,
+    PyCapsule_Destructor destructor);
+
+PyAPI_FUNC(void *) PyCapsule_GetPointer(PyObject *capsule, const char *name);
+
+PyAPI_FUNC(PyCapsule_Destructor) PyCapsule_GetDestructor(PyObject *capsule);
+
+PyAPI_FUNC(const char *) PyCapsule_GetName(PyObject *capsule);
+
+PyAPI_FUNC(void *) PyCapsule_GetContext(PyObject *capsule);
+
+PyAPI_FUNC(int) PyCapsule_IsValid(PyObject *capsule, const char *name);
+
+PyAPI_FUNC(int) PyCapsule_SetPointer(PyObject *capsule, void *pointer);
+
+PyAPI_FUNC(int) PyCapsule_SetDestructor(PyObject *capsule, PyCapsule_Destructor destructor);
+
+PyAPI_FUNC(int) PyCapsule_SetName(PyObject *capsule, const char *name);
+
+PyAPI_FUNC(int) PyCapsule_SetContext(PyObject *capsule, void *context);
+
+PyAPI_FUNC(void *) PyCapsule_Import(const char *name, int no_block);
+
+
+#define PYTHON_USING_CAPSULE
+
+#define PYCAPSULE_INSTANTIATE_DESTRUCTOR(name, destructor) \
+static void pycapsule_destructor_ ## name(PyObject *ptr) \
+{ \
+	void *p = PyCapsule_GetPointer(ptr, name); \
+	if (p) { \
+		destructor(p); \
+	} \
+} \
+
+#define PYCAPSULE_NEW(pointer, name) \
+	(PyCapsule_New(pointer, name, capsule_destructor_ ## name))
+
+#define PYCAPSULE_ISVALID(capsule, name) \
+  (PyCapsule_IsValid(capsule, name))
+
+#define PYCAPSULE_DEREFERENCE(capsule, name) \
+  (PyCapsule_GetPointer(capsule, name))
+
+#define PYCAPSULE_SET(capsule, name, value) \
+  (PyCapsule_IsValid(capsule, name) && PyCapsule_SetPointer(capsule, value))
+
+/* module and attribute should be specified as string constants */
+#define PYCAPSULE_IMPORT(module, attribute) \
+  (PyCapsule_Import(module "." attribute, 0))
+
+
+/* begin public-domain code */
+/* 
+** This code was written by Larry Hastings, 
+** and is dedicated to the public domain. 
+** It's designed to make it easy to switch 
+** from CObject to Capsule objects without losing 
+** backwards compatibility with prior versions 
+** of CPython.  You're encouraged to copy this code 
+** (including this documentation) into your 
+** Python C extension.
+** 
+** To use: 
+**    * #define a name for the pointer you store in
+**      the CObject.  If you make the CObject available
+**      as part of your module's API, this name should
+**      be "modulename.attributename", and it should be
+**      considered part of your API (so put it in your
+**      header file).
+**    * Specify a PYCAPSULE_INSTANTIATE_DESTRUCTOR(), in
+**      every C file that creates these CObjects.  This
+**      is where you specify your object's destructor.
+**    * Change all calls to CObject_FromVoidPtr()
+**      and CObject_FromVoidPointerAndDesc() into
+**      PYCAPSULE_NEW() calls.
+**    * Change all calls to PyCObject_AsVoidPtr()
+**      into PYCAPSULE_DEREFERENCE() calls.
+**    * Change all calls to PyCObject_SetVoidPtr()
+**      into PYCAPSULE_SET() calls.
+**    * Change all calls to PyCObject_Import()
+**      into PYCAPSULE_IMPORT() calls.  Note that
+**      the two arguments to PYCAPSULE_IMPORT()
+**      should both be string constants; that is,
+**      you should call
+**      PYCAPSULE_IMPORT("modulename", "attributename"),
+**      not PYCAPSULE_IMPORT(charstar1, charstar2).
+*/
+#ifndef PYTHON_USING_CAPSULE
+
+#define PYCAPSULE_INSTANTIATE_DESTRUCTOR(name, destructor) \
+static void pycapsule_destructor_ ## name(void *ptr) \
+{ \
+	destructor(p); \
+} \
+
+#define PYCAPSULE_NEW(pointer, name) \
+	(PyCObject_FromVoidPtr(pointer, pycapsule_destructor_ ## name))
+
+#define PYCAPSULE_ISVALID(capsule, name) \
+  (PyCObject_Check(capsule))
+
+#define PYCAPSULE_DEREFERENCE(capsule, name) \
+  (PyCObject_AsVoidPtr(capsule))
+
+#define PYCAPSULE_SET(capsule, name, value) \
+  (PyCObject_SetVoidPtr(capsule, value))
+
+/* module and attribute should be specified as string constants */
+#define PYCAPSULE_IMPORT(module, attribute) \
+  (PyCObject_Import(module, attribute))
+
+#endif /* PYTHON_USING_CAPSULE */
+/* end public-domain code */
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_CAPSULE_H */

Modified: python/trunk/Include/pyexpat.h
==============================================================================
--- python/trunk/Include/pyexpat.h	(original)
+++ python/trunk/Include/pyexpat.h	Thu Mar 25 01:54:54 2010
@@ -4,6 +4,7 @@
 /* note: you must import expat.h before importing this module! */
 
 #define PyExpat_CAPI_MAGIC  "pyexpat.expat_CAPI 1.0"
+#define PyExpat_CAPSULE_NAME "pyexpat.expat_CAPI"
 
 struct PyExpat_CAPI 
 {

Modified: python/trunk/Include/ucnhash.h
==============================================================================
--- python/trunk/Include/ucnhash.h	(original)
+++ python/trunk/Include/ucnhash.h	Thu Mar 25 01:54:54 2010
@@ -6,7 +6,9 @@
 extern "C" {
 #endif
 
-/* revised ucnhash CAPI interface (exported through a PyCObject) */
+/* revised ucnhash CAPI interface (exported through a "wrapper") */
+
+#define PyUnicodeData_CAPSULE_NAME "unicodedata.ucnhash_CAPI"
 
 typedef struct {
 

Modified: python/trunk/Lib/test/test_sys.py
==============================================================================
--- python/trunk/Lib/test/test_sys.py	(original)
+++ python/trunk/Lib/test/test_sys.py	Thu Mar 25 01:54:54 2010
@@ -670,6 +670,7 @@
             x = property(getx, setx, delx, "")
             check(x, size(h + '4Pi'))
         # PyCObject
+        # PyCapsule
         # XXX
         # rangeiterator
         check(iter(xrange(1)), size(h + '4l'))

Modified: python/trunk/Makefile.pre.in
==============================================================================
--- python/trunk/Makefile.pre.in	(original)
+++ python/trunk/Makefile.pre.in	Thu Mar 25 01:54:54 2010
@@ -309,6 +309,7 @@
 		Objects/bufferobject.o \
 		Objects/bytes_methods.o \
 		Objects/bytearrayobject.o \
+		Objects/capsule.o \
 		Objects/cellobject.o \
 		Objects/classobject.o \
 		Objects/cobject.o \
@@ -642,6 +643,7 @@
 		Include/pgen.h \
 		Include/pgenheaders.h \
 		Include/pyarena.h \
+		Include/pycapsule.h \
 		Include/pyctype.h \
 		Include/pydebug.h \
 		Include/pyerrors.h \

Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS	(original)
+++ python/trunk/Misc/NEWS	Thu Mar 25 01:54:54 2010
@@ -138,6 +138,12 @@
 
 - Issue #7705: Fix linking on FreeBSD.
 
+C-API
+-----
+
+- Issue #7992: A replacement PyCObject API, PyCapsule, has been backported
+  from Python 3.1.
+
 Tests
 -----
 

Modified: python/trunk/Modules/_ctypes/callproc.c
==============================================================================
--- python/trunk/Modules/_ctypes/callproc.c	(original)
+++ python/trunk/Modules/_ctypes/callproc.c	Thu Mar 25 01:54:54 2010
@@ -83,6 +83,13 @@
 #define DONT_USE_SEH
 #endif
 
+
+#define CTYPES_CAPSULE_ERROROBJ "_ctypes/callproc.c error object"
+CTYPES_CAPSULE_INSTANTIATE_DESTRUCTOR(CTYPES_CAPSULE_ERROROBJ)
+
+#define CTYPES_CAPSULE_WCHAR_T "_ctypes/callproc.c wchar_t buffer from unicode"
+CTYPES_CAPSULE_INSTANTIATE_DESTRUCTOR(CTYPES_CAPSULE_WCHAR_T)
+
 /*
   ctypes maintains thread-local storage that has space for two error numbers:
   private copies of the system 'errno' value and, on Windows, the system error code
@@ -134,14 +141,22 @@
 			return NULL;
 	}
 	errobj = PyDict_GetItem(dict, error_object_name);
-	if (errobj)
+	if (errobj) {
+#ifdef CTYPES_USING_CAPSULE
+		if (!PyCapsule_IsValid(errobj, CTYPES_CAPSULE_ERROROBJ)) {
+			PyErr_SetString(PyExc_RuntimeError,
+				"ctypes.error_object is an invalid capsule");
+			return NULL;
+		}
+#endif /* CTYPES_USING_CAPSULE */
 		Py_INCREF(errobj);
+	}
 	else {
 		void *space = PyMem_Malloc(sizeof(int) * 2);
 		if (space == NULL)
 			return NULL;
 		memset(space, 0, sizeof(int) * 2);
-		errobj = PyCObject_FromVoidPtr(space, PyMem_Free);
+		errobj = CAPSULE_NEW(space, CTYPES_CAPSULE_ERROROBJ);
 		if (errobj == NULL)
 			return NULL;
 		if (-1 == PyDict_SetItem(dict, error_object_name,
@@ -150,7 +165,7 @@
 			return NULL;
 		}
 	}
-	*pspace = (int *)PyCObject_AsVoidPtr(errobj);
+	*pspace = (int *)CAPSULE_DEREFERENCE(errobj, CTYPES_CAPSULE_ERROROBJ);
 	return errobj;
 }
 
@@ -670,7 +685,7 @@
 			return -1;
 		}
 		memset(pa->value.p, 0, size);
-		pa->keep = PyCObject_FromVoidPtr(pa->value.p, PyMem_Free);
+		pa->keep = CAPSULE_NEW(pa->value.p, CTYPES_CAPSULE_WCHAR_T);
 		if (!pa->keep) {
 			PyMem_Free(pa->value.p);
 			return -1;

Modified: python/trunk/Modules/_ctypes/cfield.c
==============================================================================
--- python/trunk/Modules/_ctypes/cfield.c	(original)
+++ python/trunk/Modules/_ctypes/cfield.c	Thu Mar 25 01:54:54 2010
@@ -10,6 +10,11 @@
 #endif
 #include "ctypes.h"
 
+
+#define CTYPES_CAPSULE_WCHAR_T "_ctypes/cfield.c wchar_t buffer from unicode"
+CTYPES_CAPSULE_INSTANTIATE_DESTRUCTOR(CTYPES_CAPSULE_WCHAR_T)
+
+
 /******************************************************************/
 /*
   PyCField_Type
@@ -1457,7 +1462,7 @@
 			return PyErr_NoMemory();
 		}
 		memset(buffer, 0, size);
-		keep = PyCObject_FromVoidPtr(buffer, PyMem_Free);
+		keep = CAPSULE_NEW(buffer, CTYPES_CAPSULE_WCHAR_T);
 		if (!keep) {
 			Py_DECREF(value);
 			PyMem_Free(buffer);

Modified: python/trunk/Modules/_ctypes/ctypes.h
==============================================================================
--- python/trunk/Modules/_ctypes/ctypes.h	(original)
+++ python/trunk/Modules/_ctypes/ctypes.h	Thu Mar 25 01:54:54 2010
@@ -445,6 +445,40 @@
 extern PyObject *ComError;
 #endif
 
+#if PY_VERSION_HEX >= 0x020700A4
+/* Use PyCapsule for 2.7 */
+
+#define CTYPES_USING_CAPSULE
+
+#define CTYPES_CAPSULE_INSTANTIATE_DESTRUCTOR(name) \
+static void capsule_destructor_ ## name(PyObject *ptr) \
+{ \
+	void *p = PyCapsule_GetPointer(ptr, name); \
+	if (p) { \
+		PyMem_Free(p); \
+	} \
+} \
+
+#define CAPSULE_NEW(pointer, name) \
+	(PyCapsule_New(pointer, name, capsule_destructor_ ## name))
+
+#define CAPSULE_DEREFERENCE(capsule, name) \
+  (PyCapsule_GetPointer(capsule, name))
+
+#else /* PY_VERSION_HEX >= 0x020700A4 */
+/* Use CObject for 2.6 and before */
+
+#define CTYPES_CAPSULE_INSTANTIATE_DESTRUCTOR(name)
+
+#define CAPSULE_NEW(pointer, name) \
+	(PyCObject_FromVoidPtr(pointer, PyMem_Free))
+
+#define CAPSULE_DEREFERENCE(capsule, name) \
+  (PyCObject_AsVoidPtr(capsule))
+
+#endif /* PY_VERSION_HEX >= 0x020700A4 */
+
+
 /*
  Local Variables:
  compile-command: "python setup.py -q build install --home ~"

Modified: python/trunk/Modules/_cursesmodule.c
==============================================================================
--- python/trunk/Modules/_cursesmodule.c	(original)
+++ python/trunk/Modules/_cursesmodule.c	Thu Mar 25 01:54:54 2010
@@ -172,7 +172,7 @@
 /*
  * Check the return code from a curses function and return None 
  * or raise an exception as appropriate.  These are exported using the
- * CObject API. 
+ * capsule API.
  */
 
 static PyObject *
@@ -2745,8 +2745,8 @@
 		return;
 	ModDict = d; /* For PyCurses_InitScr to use later */
 
-	/* Add a CObject for the C API */
-	c_api_object = PyCObject_FromVoidPtr((void *)PyCurses_API, NULL);
+	/* Add a capsule for the C API */
+	c_api_object = PyCapsule_New(PyCurses_API, PyCurses_CAPSULE_NAME, NULL);
 	PyDict_SetItemString(d, "_C_API", c_api_object);
 	Py_DECREF(c_api_object);
 

Modified: python/trunk/Modules/_elementtree.c
==============================================================================
--- python/trunk/Modules/_elementtree.c	(original)
+++ python/trunk/Modules/_elementtree.c	Thu Mar 25 01:54:54 2010
@@ -3059,7 +3059,7 @@
 
 #if defined(USE_PYEXPAT_CAPI)
     /* link against pyexpat, if possible */
-    expat_capi = PyCObject_Import("pyexpat", "expat_CAPI");
+    expat_capi = PyCapsule_Import(PyExpat_CAPSULE_NAME, 0);
     if (expat_capi) {
         /* check that it's usable */
         if (strcmp(expat_capi->magic, PyExpat_CAPI_MAGIC) != 0 ||

Modified: python/trunk/Modules/_testcapimodule.c
==============================================================================
--- python/trunk/Modules/_testcapimodule.c	(original)
+++ python/trunk/Modules/_testcapimodule.c	Thu Mar 25 01:54:54 2010
@@ -1428,6 +1428,157 @@
 #undef CHECK_1_FORMAT
 }
 
+/* Coverage testing of capsule objects. */
+
+static const char *capsule_name = "capsule name";
+static       char *capsule_pointer = "capsule pointer";
+static       char *capsule_context = "capsule context";
+static const char *capsule_error = NULL;
+static int
+capsule_destructor_call_count = 0;
+
+static void
+capsule_destructor(PyObject *o) {
+	capsule_destructor_call_count++;
+	if (PyCapsule_GetContext(o) != capsule_context) {
+		capsule_error = "context did not match in destructor!";
+	} else if (PyCapsule_GetDestructor(o) != capsule_destructor) {
+		capsule_error = "destructor did not match in destructor!  (woah!)";
+	} else if (PyCapsule_GetName(o) != capsule_name) {
+		capsule_error = "name did not match in destructor!";
+	} else if (PyCapsule_GetPointer(o, capsule_name) != capsule_pointer) {
+		capsule_error = "pointer did not match in destructor!";
+	}
+}
+
+typedef struct {
+	char *name;
+	char *module;
+	char *attribute;
+} known_capsule;
+
+static PyObject *
+test_capsule(PyObject *self, PyObject *args)
+{
+	PyObject *object;
+	const char *error = NULL;
+	void *pointer;
+	void *pointer2;
+	known_capsule known_capsules[] = {
+		#define KNOWN_CAPSULE(module, name)	{ module "." name, module, name }
+		KNOWN_CAPSULE("_socket", "CAPI"),
+		KNOWN_CAPSULE("_curses", "_C_API"),
+		KNOWN_CAPSULE("datetime", "datetime_CAPI"),
+		{ NULL, NULL },
+	};
+	known_capsule *known = &known_capsules[0];
+
+#define FAIL(x) { error = (x); goto exit; }
+
+#define CHECK_DESTRUCTOR \
+	if (capsule_error) { \
+		FAIL(capsule_error); \
+	} \
+	else if (!capsule_destructor_call_count) {	\
+		FAIL("destructor not called!"); \
+	} \
+	capsule_destructor_call_count = 0; \
+
+	object = PyCapsule_New(capsule_pointer, capsule_name, capsule_destructor);
+	PyCapsule_SetContext(object, capsule_context);
+	capsule_destructor(object);
+	CHECK_DESTRUCTOR;
+	Py_DECREF(object);
+	CHECK_DESTRUCTOR;
+
+	object = PyCapsule_New(known, "ignored", NULL);
+	PyCapsule_SetPointer(object, capsule_pointer);
+	PyCapsule_SetName(object, capsule_name);
+	PyCapsule_SetDestructor(object, capsule_destructor);
+	PyCapsule_SetContext(object, capsule_context);
+	capsule_destructor(object);
+	CHECK_DESTRUCTOR;
+	/* intentionally access using the wrong name */
+	pointer2 = PyCapsule_GetPointer(object, "the wrong name");
+	if (!PyErr_Occurred()) {
+		FAIL("PyCapsule_GetPointer should have failed but did not!");
+	}
+	PyErr_Clear();
+	if (pointer2) {
+		if (pointer2 == capsule_pointer) {
+			FAIL("PyCapsule_GetPointer should not have"
+				 " returned the internal pointer!");
+		} else {
+			FAIL("PyCapsule_GetPointer should have "
+				 "returned NULL pointer but did not!");
+		}
+	}
+	PyCapsule_SetDestructor(object, NULL);
+	Py_DECREF(object);
+	if (capsule_destructor_call_count) {
+		FAIL("destructor called when it should not have been!");
+	}
+
+	for (known = &known_capsules[0]; known->module != NULL; known++) {
+		/* yeah, ordinarily I wouldn't do this either,
+		   but it's fine for this test harness.
+		*/
+		static char buffer[256];
+#undef FAIL
+#define FAIL(x) \
+		{ \
+		sprintf(buffer, "%s module: \"%s\" attribute: \"%s\"", \
+			x, known->module, known->attribute); \
+		error = buffer; \
+		goto exit; \
+		} \
+
+		PyObject *module = PyImport_ImportModule(known->module);
+		if (module) {
+			pointer = PyCapsule_Import(known->name, 0);
+			if (!pointer) {
+				Py_DECREF(module);
+				FAIL("PyCapsule_GetPointer returned NULL unexpectedly!");
+			}
+			object = PyObject_GetAttrString(module, known->attribute);
+			if (!object) {
+				Py_DECREF(module);
+				return NULL;
+			}
+			pointer2 = PyCapsule_GetPointer(object,
+						"weebles wobble but they don't fall down");
+			if (!PyErr_Occurred()) {
+				Py_DECREF(object);
+				Py_DECREF(module);
+				FAIL("PyCapsule_GetPointer should have failed but did not!");
+			}
+			PyErr_Clear();
+			if (pointer2) {
+				Py_DECREF(module);
+				Py_DECREF(object);
+				if (pointer2 == pointer) {
+					FAIL("PyCapsule_GetPointer should not have"
+						 " returned its internal pointer!");
+				} else {
+					FAIL("PyCapsule_GetPointer should have"
+						 " returned NULL pointer but did not!");
+				}
+			}
+			Py_DECREF(object);
+			Py_DECREF(module);
+		}
+		else
+			PyErr_Clear();
+	}
+
+  exit:
+	if (error) {
+		return raiseTestError("test_capsule", error);
+	}
+	Py_RETURN_NONE;
+#undef FAIL
+}
+
 /* This is here to provide a docstring for test_descr. */
 static PyObject *
 test_with_docstring(PyObject *self)
@@ -1539,6 +1690,7 @@
 	{"_test_thread_state",  test_thread_state, 		 METH_VARARGS},
 	{"_pending_threadfunc",	pending_threadfunc,		 METH_VARARGS},
 #endif
+	{"test_capsule", (PyCFunction)test_capsule, METH_NOARGS},
 	{"traceback_print", traceback_print, 	         METH_VARARGS},
 	{"code_newempty", code_newempty, 	         METH_VARARGS},
 	{"make_exception_with_doc", (PyCFunction)make_exception_with_doc,

Modified: python/trunk/Modules/cStringIO.c
==============================================================================
--- python/trunk/Modules/cStringIO.c	(original)
+++ python/trunk/Modules/cStringIO.c	Thu Mar 25 01:54:54 2010
@@ -761,8 +761,8 @@
   Py_TYPE(&Otype)=&PyType_Type;
   if (PyType_Ready(&Otype) < 0) return;
   if (PyType_Ready(&Itype) < 0) return;
-  PyDict_SetItemString(d,"cStringIO_CAPI",
-		       v = PyCObject_FromVoidPtr(&CAPI,NULL));
+  v = PyCapsule_New(&CAPI, PycStringIO_CAPSULE_NAME, NULL);
+  PyDict_SetItemString(d,"cStringIO_CAPI", v);
   Py_XDECREF(v);
 
   /* Export Types */

Modified: python/trunk/Modules/cjkcodecs/cjkcodecs.h
==============================================================================
--- python/trunk/Modules/cjkcodecs/cjkcodecs.h	(original)
+++ python/trunk/Modules/cjkcodecs/cjkcodecs.h	Thu Mar 25 01:54:54 2010
@@ -282,7 +282,7 @@
 		return NULL;
 	}
 
-	codecobj = PyCObject_FromVoidPtr((void *)codec, NULL);
+	codecobj = PyCapsule_New((void *)codec, PyMultibyteCodec_CAPSULE_NAME, NULL);
 	if (codecobj == NULL)
 		return NULL;
 
@@ -307,7 +307,7 @@
 		int r;
 		strcpy(mhname + sizeof("__map_") - 1, h->charset);
 		r = PyModule_AddObject(module, mhname,
-				PyCObject_FromVoidPtr((void *)h, NULL));
+				PyCapsule_New((void *)h, PyMultibyteCodec_CAPSULE_NAME, NULL));
 		if (r == -1)
 			return -1;
 	}
@@ -362,14 +362,14 @@
 	o = PyObject_GetAttrString(mod, (char*)symbol);
 	if (o == NULL)
 		goto errorexit;
-	else if (!PyCObject_Check(o)) {
+	else if (!PyCapsule_IsValid(o, PyMultibyteCodec_CAPSULE_NAME)) {
 		PyErr_SetString(PyExc_ValueError,
-				"map data must be a CObject.");
+				"map data must be a Capsule.");
 		goto errorexit;
 	}
 	else {
 		struct dbcs_map *map;
-		map = PyCObject_AsVoidPtr(o);
+		map = PyCapsule_GetPointer(o, PyMultibyteCodec_CAPSULE_NAME);
 		if (encmap != NULL)
 			*encmap = map->encmap;
 		if (decmap != NULL)

Modified: python/trunk/Modules/cjkcodecs/multibytecodec.c
==============================================================================
--- python/trunk/Modules/cjkcodecs/multibytecodec.c	(original)
+++ python/trunk/Modules/cjkcodecs/multibytecodec.c	Thu Mar 25 01:54:54 2010
@@ -1774,12 +1774,12 @@
 	MultibyteCodecObject *self;
 	MultibyteCodec *codec;
 
-	if (!PyCObject_Check(arg)) {
+	if (!PyCapsule_IsValid(arg, PyMultibyteCodec_CAPSULE_NAME)) {
 		PyErr_SetString(PyExc_ValueError, "argument type invalid");
 		return NULL;
 	}
 
-	codec = PyCObject_AsVoidPtr(arg);
+	codec = PyCapsule_GetPointer(arg, PyMultibyteCodec_CAPSULE_NAME);
 	if (codec->codecinit != NULL && codec->codecinit(codec->config) != 0)
 		return NULL;
 

Modified: python/trunk/Modules/cjkcodecs/multibytecodec.h
==============================================================================
--- python/trunk/Modules/cjkcodecs/multibytecodec.h	(original)
+++ python/trunk/Modules/cjkcodecs/multibytecodec.h	Thu Mar 25 01:54:54 2010
@@ -132,6 +132,9 @@
 #define MBENC_FLUSH		0x0001 /* encode all characters encodable */
 #define MBENC_MAX		MBENC_FLUSH
 
+#define PyMultibyteCodec_CAPSULE_NAME "multibytecodec.__map_*"
+
+
 #ifdef __cplusplus
 }
 #endif

Modified: python/trunk/Modules/datetimemodule.c
==============================================================================
--- python/trunk/Modules/datetimemodule.c	(original)
+++ python/trunk/Modules/datetimemodule.c	Thu Mar 25 01:54:54 2010
@@ -4856,11 +4856,10 @@
 	Py_INCREF(&PyDateTime_TZInfoType);
 	PyModule_AddObject(m, "tzinfo", (PyObject *) &PyDateTime_TZInfoType);
 
-        x = PyCObject_FromVoidPtrAndDesc(&CAPI, (void*) DATETIME_API_MAGIC,
-                NULL);
-        if (x == NULL)
-            return;
-        PyModule_AddObject(m, "datetime_CAPI", x);
+	x = PyCapsule_New(&CAPI, PyDateTime_CAPSULE_NAME, NULL);
+	if (x == NULL)
+		return NULL;
+	PyModule_AddObject(m, "datetime_CAPI", x);
 
 	/* A 4-year cycle has an extra leap day over what we'd get from
 	 * pasting together 4 single years.

Modified: python/trunk/Modules/pyexpat.c
==============================================================================
--- python/trunk/Modules/pyexpat.c	(original)
+++ python/trunk/Modules/pyexpat.c	Thu Mar 25 01:54:54 2010
@@ -2053,8 +2053,8 @@
     capi.SetUnknownEncodingHandler = XML_SetUnknownEncodingHandler;
     capi.SetUserData = XML_SetUserData;
     
-    /* export as cobject */
-    capi_object = PyCObject_FromVoidPtr(&capi, NULL);
+    /* export using capsule */
+    capi_object = PyCapsule_New(&capi, PyExpat_CAPSULE_NAME, NULL);
     if (capi_object)
         PyModule_AddObject(m, "expat_CAPI", capi_object);
 }

Modified: python/trunk/Modules/socketmodule.c
==============================================================================
--- python/trunk/Modules/socketmodule.c	(original)
+++ python/trunk/Modules/socketmodule.c	Thu Mar 25 01:54:54 2010
@@ -4496,7 +4496,7 @@
 
 	/* Export C API */
 	if (PyModule_AddObject(m, PySocket_CAPI_NAME,
-	       PyCObject_FromVoidPtr((void *)&PySocketModuleAPI, NULL)
+	       PyCapsule_New(&PySocketModuleAPI, PySocket_CAPSULE_NAME, NULL)
 				 ) != 0)
 		return;
 

Modified: python/trunk/Modules/socketmodule.h
==============================================================================
--- python/trunk/Modules/socketmodule.h	(original)
+++ python/trunk/Modules/socketmodule.h	Thu Mar 25 01:54:54 2010
@@ -78,6 +78,7 @@
 /* Python module and C API name */
 #define PySocket_MODULE_NAME	"_socket"
 #define PySocket_CAPI_NAME	"CAPI"
+#define PySocket_CAPSULE_NAME  (PySocket_MODULE_NAME "." PySocket_CAPI_NAME)
 
 /* Abstract the socket file descriptor type */
 #ifdef MS_WINDOWS
@@ -142,12 +143,12 @@
     the _socket module. Since cross-DLL linking introduces a lot of
     problems on many platforms, the "trick" is to wrap the
     C API of a module in a struct which then gets exported to
-    other modules via a PyCObject.
+    other modules via a PyCapsule.
 
     The code in socketmodule.c defines this struct (which currently
     only contains the type object reference, but could very
     well also include other C APIs needed by other modules)
-    and exports it as PyCObject via the module dictionary
+    and exports it as PyCapsule via the module dictionary
     under the name "CAPI".
 
     Other modules can now include the socketmodule.h file
@@ -226,33 +227,18 @@
 static
 int PySocketModule_ImportModuleAndAPI(void)
 {
-	PyObject *mod = 0, *v = 0;
-	char *apimodule = PySocket_MODULE_NAME;
-	char *apiname = PySocket_CAPI_NAME;
 	void *api;
 
-	DPRINTF("Importing the %s C API...\n", apimodule);
-	mod = PyImport_ImportModuleNoBlock(apimodule);
-	if (mod == NULL)
-		goto onError;
-	DPRINTF(" %s package found\n", apimodule);
-	v = PyObject_GetAttrString(mod, apiname);
-	if (v == NULL)
-		goto onError;
-	Py_DECREF(mod);
-	DPRINTF(" API object %s found\n", apiname);
-	api = PyCObject_AsVoidPtr(v);
+  DPRINTF(" Loading capsule %s\n", PySocket_CAPSULE_NAME);
+  api = PyCapsule_Import(PySocket_CAPSULE_NAME, 1);
 	if (api == NULL)
 		goto onError;
-	Py_DECREF(v);
 	memcpy(&PySocketModule, api, sizeof(PySocketModule));
 	DPRINTF(" API object loaded and initialized.\n");
 	return 0;
 
  onError:
 	DPRINTF(" not found.\n");
-	Py_XDECREF(mod);
-	Py_XDECREF(v);
 	return -1;
 }
 

Modified: python/trunk/Modules/unicodedata.c
==============================================================================
--- python/trunk/Modules/unicodedata.c	(original)
+++ python/trunk/Modules/unicodedata.c	Thu Mar 25 01:54:54 2010
@@ -1261,7 +1261,7 @@
         PyModule_AddObject(m, "ucd_3_2_0", v);
 
     /* Export C API */
-    v = PyCObject_FromVoidPtr((void *) &hashAPI, NULL);
+    v = PyCapsule_New((void *)&hashAPI, PyUnicodeData_CAPSULE_NAME, NULL);
     if (v != NULL)
         PyModule_AddObject(m, "ucnhash_CAPI", v);
 }

Added: python/trunk/Objects/capsule.c
==============================================================================
--- (empty file)
+++ python/trunk/Objects/capsule.c	Thu Mar 25 01:54:54 2010
@@ -0,0 +1,324 @@
+/* Wrap void * pointers to be passed between C modules */
+
+#include "Python.h"
+
+/* Internal structure of PyCapsule */
+typedef struct {
+    PyObject_HEAD
+    void *pointer;
+    const char *name;
+    void *context;
+    PyCapsule_Destructor destructor;
+} PyCapsule;
+
+
+
+static int
+_is_legal_capsule(PyCapsule *capsule, const char *invalid_capsule)
+{
+    if (!capsule || !PyCapsule_CheckExact(capsule) || capsule->pointer == NULL) {
+        PyErr_SetString(PyExc_ValueError, invalid_capsule);
+        return 0;
+    }
+    return 1;
+}
+
+#define is_legal_capsule(capsule, name) \
+    (_is_legal_capsule(capsule, \
+     name " called with invalid PyCapsule object"))
+
+
+static int
+name_matches(const char *name1, const char *name2) {
+    /* if either is NULL, */
+    if (!name1 || !name2) {
+        /* they're only the same if they're both NULL. */
+        return name1 == name2;
+    }
+    return !strcmp(name1, name2);
+}
+
+
+
+PyObject *
+PyCapsule_New(void *pointer, const char *name, PyCapsule_Destructor destructor)
+{
+    PyCapsule *capsule;
+
+    if (!pointer) {
+        PyErr_SetString(PyExc_ValueError, "PyCapsule_New called with null pointer");
+        return NULL;
+    }
+
+    capsule = PyObject_NEW(PyCapsule, &PyCapsule_Type);
+    if (capsule == NULL) {
+        return NULL;
+    }
+
+    capsule->pointer = pointer;
+    capsule->name = name;
+    capsule->context = NULL;
+    capsule->destructor = destructor;
+
+    return (PyObject *)capsule;
+}
+
+
+int
+PyCapsule_IsValid(PyObject *o, const char *name)
+{
+    PyCapsule *capsule = (PyCapsule *)o;
+
+    return (capsule != NULL &&
+            PyCapsule_CheckExact(capsule) &&
+            capsule->pointer != NULL &&
+            name_matches(capsule->name, name));
+}
+
+
+void *
+PyCapsule_GetPointer(PyObject *o, const char *name)
+{
+    PyCapsule *capsule = (PyCapsule *)o;
+
+    if (!is_legal_capsule(capsule, "PyCapsule_GetPointer")) {
+        return NULL;
+    }
+
+    if (!name_matches(name, capsule->name)) {
+        PyErr_SetString(PyExc_ValueError, "PyCapsule_GetPointer called with incorrect name");
+        return NULL;
+    }
+
+    return capsule->pointer;
+}
+
+
+const char *
+PyCapsule_GetName(PyObject *o)
+{
+    PyCapsule *capsule = (PyCapsule *)o;
+
+    if (!is_legal_capsule(capsule, "PyCapsule_GetName")) {
+        return NULL;
+    }
+    return capsule->name;
+}
+
+
+PyCapsule_Destructor
+PyCapsule_GetDestructor(PyObject *o)
+{
+    PyCapsule *capsule = (PyCapsule *)o;
+
+    if (!is_legal_capsule(capsule, "PyCapsule_GetDestructor")) {
+        return NULL;
+    }
+    return capsule->destructor;
+}
+
+
+void *
+PyCapsule_GetContext(PyObject *o)
+{
+    PyCapsule *capsule = (PyCapsule *)o;
+
+    if (!is_legal_capsule(capsule, "PyCapsule_GetContext")) {
+        return NULL;
+    }
+    return capsule->context;
+}
+
+
+int
+PyCapsule_SetPointer(PyObject *o, void *pointer)
+{
+    PyCapsule *capsule = (PyCapsule *)o;
+
+    if (!pointer) {
+        PyErr_SetString(PyExc_ValueError, "PyCapsule_SetPointer called with null pointer");
+        return -1;
+    }
+
+    if (!is_legal_capsule(capsule, "PyCapsule_SetPointer")) {
+        return -1;
+    }
+
+    capsule->pointer = pointer;
+    return 0;
+}
+
+
+int
+PyCapsule_SetName(PyObject *o, const char *name)
+{
+    PyCapsule *capsule = (PyCapsule *)o;
+
+    if (!is_legal_capsule(capsule, "PyCapsule_SetName")) {
+        return -1;
+    }
+
+    capsule->name = name;
+    return 0;
+}
+
+
+int
+PyCapsule_SetDestructor(PyObject *o, PyCapsule_Destructor destructor)
+{
+    PyCapsule *capsule = (PyCapsule *)o;
+
+    if (!is_legal_capsule(capsule, "PyCapsule_SetDestructor")) {
+        return -1;
+    }
+
+    capsule->destructor = destructor;
+    return 0;
+}
+
+
+int
+PyCapsule_SetContext(PyObject *o, void *context)
+{
+    PyCapsule *capsule = (PyCapsule *)o;
+
+    if (!is_legal_capsule(capsule, "PyCapsule_SetContext")) {
+        return -1;
+    }
+
+    capsule->context = context;
+    return 0;
+}
+
+
+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;
+    }
+
+    /* compare attribute name to module.name by hand */
+    if (PyCapsule_IsValid(object, name)) {
+        PyCapsule *capsule = (PyCapsule *)object;
+        return_value = capsule->pointer;
+    } 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;
+}
+
+
+static void
+capsule_dealloc(PyObject *o)
+{
+    PyCapsule *capsule = (PyCapsule *)o;
+    if (capsule->destructor) {
+        capsule->destructor(o);
+    }
+    PyObject_DEL(o);
+}
+
+
+static PyObject *
+capsule_repr(PyObject *o)
+{
+    PyCapsule *capsule = (PyCapsule *)o;
+    const char *name;
+    const char *quote;
+
+    if (capsule->name) {
+        quote = "\"";
+        name = capsule->name;
+    } else {
+        quote = "";
+        name = "NULL";
+    }
+
+    return PyString_FromFormat("<capsule object %s%s%s at %p>",
+        quote, name, quote, capsule);
+}
+
+
+
+PyDoc_STRVAR(PyCapsule_Type__doc__,
+"Capsule objects let you wrap a C \"void *\" pointer in a Python\n\
+object.  They're a way of passing data through the Python interpreter\n\
+without creating your own custom type.\n\
+\n\
+Capsules are used for communication between extension modules.\n\
+They provide a way for an extension module to export a C interface\n\
+to other extension modules, so that extension modules can use the\n\
+Python import mechanism to link to one another.\n\
+");
+
+PyTypeObject PyCapsule_Type = {
+    PyVarObject_HEAD_INIT(&PyType_Type, 0)
+    "PyCapsule",		/*tp_name*/
+    sizeof(PyCapsule),		/*tp_basicsize*/
+    0,				/*tp_itemsize*/
+    /* methods */
+    capsule_dealloc, /*tp_dealloc*/
+    0,				/*tp_print*/
+    0,				/*tp_getattr*/
+    0,				/*tp_setattr*/
+    0,				/*tp_reserved*/
+    capsule_repr, /*tp_repr*/
+    0,				/*tp_as_number*/
+    0,				/*tp_as_sequence*/
+    0,				/*tp_as_mapping*/
+    0,				/*tp_hash*/
+    0,				/*tp_call*/
+    0,				/*tp_str*/
+    0,				/*tp_getattro*/
+    0,				/*tp_setattro*/
+    0,				/*tp_as_buffer*/
+    0,				/*tp_flags*/
+    PyCapsule_Type__doc__	/*tp_doc*/
+};
+
+

Modified: python/trunk/Objects/object.c
==============================================================================
--- python/trunk/Objects/object.c	(original)
+++ python/trunk/Objects/object.c	Thu Mar 25 01:54:54 2010
@@ -2269,6 +2269,10 @@
 #endif
 
 
+/* Hack to force loading of capsule.o */
+PyTypeObject *_Py_capsule_hack = &PyCapsule_Type;
+
+
 /* Hack to force loading of cobject.o */
 PyTypeObject *_Py_cobject_hack = &PyCObject_Type;
 

Modified: python/trunk/Objects/unicodeobject.c
==============================================================================
--- python/trunk/Objects/unicodeobject.c	(original)
+++ python/trunk/Objects/unicodeobject.c	Thu Mar 25 01:54:54 2010
@@ -2889,16 +2889,7 @@
             message = "malformed \\N character escape";
             if (ucnhash_CAPI == NULL) {
                 /* load the unicode data module */
-                PyObject *m, *api;
-                m = PyImport_ImportModuleNoBlock("unicodedata");
-                if (m == NULL)
-                    goto ucnhashError;
-                api = PyObject_GetAttrString(m, "ucnhash_CAPI");
-                Py_DECREF(m);
-                if (api == NULL)
-                    goto ucnhashError;
-                ucnhash_CAPI = (_PyUnicode_Name_CAPI *)PyCObject_AsVoidPtr(api);
-                Py_DECREF(api);
+                ucnhash_CAPI = (_PyUnicode_Name_CAPI *)PyCapsule_Import(PyUnicodeData_CAPSULE_NAME, 1);
                 if (ucnhash_CAPI == NULL)
                     goto ucnhashError;
             }

Modified: python/trunk/PC/VS7.1/pythoncore.vcproj
==============================================================================
--- python/trunk/PC/VS7.1/pythoncore.vcproj	(original)
+++ python/trunk/PC/VS7.1/pythoncore.vcproj	Thu Mar 25 01:54:54 2010
@@ -461,6 +461,9 @@
 			RelativePath="..\..\Objects\bytes_methods.c">
 		</File>
 		<File
+			RelativePath="..\..\Objects\capsule.c">
+		</File>
+		<File
 			RelativePath="..\..\Objects\cellobject.c">
 		</File>
 		<File

Modified: python/trunk/PC/VS8.0/pythoncore.vcproj
==============================================================================
--- python/trunk/PC/VS8.0/pythoncore.vcproj	(original)
+++ python/trunk/PC/VS8.0/pythoncore.vcproj	Thu Mar 25 01:54:54 2010
@@ -855,6 +855,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\Include\pycapsule.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\Include\pyctype.h"
 				>
 			</File>
@@ -1419,6 +1423,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\Objects\capsule.c"
+				>
+			</File>
+			<File
 				RelativePath="..\..\Objects\cellobject.c"
 				>
 			</File>

Modified: python/trunk/PC/os2emx/python27.def
==============================================================================
--- python/trunk/PC/os2emx/python27.def	(original)
+++ python/trunk/PC/os2emx/python27.def	Thu Mar 25 01:54:54 2010
@@ -210,6 +210,19 @@
   "PyInstance_Type"
   "PyMethod_Type"
 
+; From python27_s.lib(capsule)
+  "PyCapsule_GetContext"
+  "PyCapsule_GetDestructor"
+  "PyCapsule_GetName"
+  "PyCapsule_GetPointer"
+  "PyCapsule_Import"
+  "PyCapsule_IsValid"
+  "PyCapsule_New"
+  "PyCapsule_SetContext"
+  "PyCapsule_SetDestructor"
+  "PyCapsule_SetName"
+  "PyCapsule_SetPointer"
+
 ; From python27_s.lib(cobject)
   "PyCObject_FromVoidPtr"
   "PyCObject_FromVoidPtrAndDesc"

Modified: python/trunk/PC/os2vacpp/python.def
==============================================================================
--- python/trunk/PC/os2vacpp/python.def	(original)
+++ python/trunk/PC/os2vacpp/python.def	Thu Mar 25 01:54:54 2010
@@ -6,6 +6,7 @@
 EXPORTS
                ; Data
                PyCFunction_Type
+               PyCapsule_Type
                PyCObject_Type
                PyClass_Type
                PyCode_Type
@@ -75,6 +76,7 @@
                _Py_TrueStruct
                _Py_ZeroStruct
                _Py_abstract_hack
+               _Py_capsule_hack
                _Py_cobject_hack
                _Py_re_syntax
                _Py_re_syntax_table
@@ -89,6 +91,17 @@
                PyCFunction_GetFunction
                PyCFunction_GetSelf
                PyCFunction_New
+               PyCapsule_GetContext
+               PyCapsule_GetDestructor
+               PyCapsule_GetName
+               PyCapsule_GetPointer
+               PyCapsule_Import
+               PyCapsule_IsValid
+               PyCapsule_New
+               PyCapsule_SetContext
+               PyCapsule_SetDestructor
+               PyCapsule_SetName
+               PyCapsule_SetPointer
                PyCObject_AsVoidPtr
                PyCObject_FromVoidPtrAndDesc
                PyCObject_FromVoidPtr

Modified: python/trunk/Python/compile.c
==============================================================================
--- python/trunk/Python/compile.c	(original)
+++ python/trunk/Python/compile.c	Thu Mar 25 01:54:54 2010
@@ -181,6 +181,8 @@
 static PyCodeObject *assemble(struct compiler *, int addNone);
 static PyObject *__doc__;
 
+#define COMPILER_CAPSULE_NAME_COMPILER_UNIT "compile.c compiler unit"
+
 PyObject *
 _Py_Mangle(PyObject *privateobj, PyObject *ident)
 {
@@ -490,13 +492,13 @@
 
 	/* Push the old compiler_unit on the stack. */
 	if (c->u) {
-		PyObject *wrapper = PyCObject_FromVoidPtr(c->u, NULL);
-		if (!wrapper || PyList_Append(c->c_stack, wrapper) < 0) {
-			Py_XDECREF(wrapper);
+		PyObject *capsule = PyCapsule_New(c->u, COMPILER_CAPSULE_NAME_COMPILER_UNIT, NULL);
+		if (!capsule || PyList_Append(c->c_stack, capsule) < 0) {
+			Py_XDECREF(capsule);
 			compiler_unit_free(u);
 			return 0;
 		}
-		Py_DECREF(wrapper);
+		Py_DECREF(capsule);
 		u->u_private = c->u->u_private;
 		Py_XINCREF(u->u_private);
 	}
@@ -513,15 +515,15 @@
 compiler_exit_scope(struct compiler *c)
 {
 	int n;
-	PyObject *wrapper;
+	PyObject *capsule;
 
 	c->c_nestlevel--;
 	compiler_unit_free(c->u);
 	/* Restore c->u to the parent unit. */
 	n = PyList_GET_SIZE(c->c_stack) - 1;
 	if (n >= 0) {
-		wrapper = PyList_GET_ITEM(c->c_stack, n);
-		c->u = (struct compiler_unit *)PyCObject_AsVoidPtr(wrapper);
+		capsule = PyList_GET_ITEM(c->c_stack, n);
+		c->u = (struct compiler_unit *)PyCapsule_GetPointer(capsule, COMPILER_CAPSULE_NAME_COMPILER_UNIT);
 		assert(c->u);
 		/* we are deleting from a list so this really shouldn't fail */
 		if (PySequence_DelItem(c->c_stack, n) < 0)

Modified: python/trunk/Python/getargs.c
==============================================================================
--- python/trunk/Python/getargs.c	(original)
+++ python/trunk/Python/getargs.c	Thu Mar 25 01:54:54 2010
@@ -139,22 +139,33 @@
 
 /* Handle cleanup of allocated memory in case of exception */
 
+#define GETARGS_CAPSULE_NAME_CLEANUP_PTR "getargs.cleanup_ptr"
+#define GETARGS_CAPSULE_NAME_CLEANUP_BUFFER "getargs.cleanup_buffer"
+
 static void
-cleanup_ptr(void *ptr)
+cleanup_ptr(PyObject *self)
 {
-	PyMem_FREE(ptr);
+	void *ptr = PyCapsule_GetPointer(self, GETARGS_CAPSULE_NAME_CLEANUP_PTR);
+	if (ptr) {
+	  PyMem_FREE(ptr);
+	}
 }
 
 static void
-cleanup_buffer(void *ptr)
+cleanup_buffer(PyObject *self)
 {
-	PyBuffer_Release((Py_buffer *) ptr);
+	Py_buffer *ptr = (Py_buffer *)PyCapsule_GetPointer(self, GETARGS_CAPSULE_NAME_CLEANUP_BUFFER);
+	if (ptr) {
+		PyBuffer_Release(ptr);
+	}
 }
 
 static int
-addcleanup(void *ptr, PyObject **freelist, void (*destr)(void *))
+addcleanup(void *ptr, PyObject **freelist, PyCapsule_Destructor destr)
 {
 	PyObject *cobj;
+	const char *name;
+
 	if (!*freelist) {
 		*freelist = PyList_New(0);
 		if (!*freelist) {
@@ -162,7 +173,15 @@
 			return -1;
 		}
 	}
-	cobj = PyCObject_FromVoidPtr(ptr, destr);
+
+	if (destr == cleanup_ptr) {
+		name = GETARGS_CAPSULE_NAME_CLEANUP_PTR;
+	} else if (destr == cleanup_buffer) {
+		name = GETARGS_CAPSULE_NAME_CLEANUP_BUFFER;
+	} else {
+		return -1;
+	}
+	cobj = PyCapsule_New(ptr, name, destr);
 	if (!cobj) {
 		destr(ptr);
 		return -1;
@@ -183,8 +202,7 @@
 		   don't get called. */
 		Py_ssize_t len = PyList_GET_SIZE(freelist), i;
 		for (i = 0; i < len; i++)
-			((PyCObject *) PyList_GET_ITEM(freelist, i))
-				->destructor = NULL;
+			PyCapsule_SetDestructor(PyList_GET_ITEM(freelist, i), NULL);
 	}
 	Py_XDECREF(freelist);
 	return retval;


More information about the Python-checkins mailing list