cpython: 28849d00a41e (original) (raw)
Mercurial > cpython
changeset 75337:28849d00a41e 3.2
Propagate changes for issues #13053 and #13086 from 2.7 to 3.2. (Doc only.) [#13053]
Larry Hastings larry@hastings.org | |
---|---|
date | Tue, 28 Feb 2012 16:21:47 -0800 |
parents | 8d2ffe1f25d3 |
children | c316e8a4a5e2 cde7fa40b289 |
files | Doc/howto/cporting.rst Doc/includes/capsulethunk.h |
diffstat | 2 files changed, 219 insertions(+), 26 deletions(-)[+] [-] Doc/howto/cporting.rst 111 Doc/includes/capsulethunk.h 134 |
line wrap: on
line diff
--- a/Doc/howto/cporting.rst +++ b/Doc/howto/cporting.rst @@ -2,27 +2,28 @@ .. _cporting-howto: - -Porting Extension Modules to 3.0 - + +Porting Extension Modules to Python 3 + :author: Benjamin Peterson .. topic:: Abstract
- Although changing the C-API was not one of Python 3.0's objectives, the many
- Python level changes made leaving 2.x's API intact impossible. In fact, some
- changes such as :func:
int
and :func:long
unification are more obvious on - the C level. This document endeavors to document incompatibilities and how
- they can be worked around.
- Although changing the C-API was not one of Python 3's objectives,
- the many Python-level changes made leaving Python 2's API intact
- impossible. In fact, some changes such as :func:
int
and - :func:
long
unification are more obvious on the C level. This - document endeavors to document incompatibilities and how they can
- be worked around.
Conditional compilation
=======================
-The easiest way to compile only some code for 3.0 is to check if
-:c:macro:PY_MAJOR_VERSION
is greater than or equal to 3. ::
+The easiest way to compile only some code for Python 3 is to check
+if :c:macro:PY_MAJOR_VERSION
is greater than or equal to 3. ::
#if PY_MAJOR_VERSION >= 3
#define IS_PY3K
@@ -35,7 +36,7 @@ conditional blocks.
Changes to Object APIs
======================
-Python 3.0 merged together some types with similar functions while cleanly
+Python 3 merged together some types with similar functions while cleanly
separating others.
@@ -43,14 +44,14 @@ str/unicode Unification
-----------------------
-Python 3.0's :func:str
(PyString_*
functions in C) type is equivalent to
-2.x's :func:unicode
(PyUnicode_*
). The old 8-bit string type has become
-:func:bytes
. Python 2.6 and later provide a compatibility header,
+Python 3's :func:str
(PyString_*
functions in C) type is equivalent to
+Python 2's :func:unicode
(PyUnicode_*
). The old 8-bit string type has
+become :func:bytes
. Python 2.6 and later provide a compatibility header,
:file:bytesobject.h
, mapping PyBytes
names to PyString
ones. For best
-compatibility with 3.0, :c:type:PyUnicode
should be used for textual data and
+compatibility with Python 3, :c:type:PyUnicode
should be used for textual data and
:c:type:PyBytes
for binary data. It's also important to remember that
-:c:type:PyBytes
and :c:type:PyUnicode
in 3.0 are not interchangeable like
-:c:type:PyString
and :c:type:PyUnicode
are in 2.x. The following example
+:c:type:PyBytes
and :c:type:PyUnicode
in Python 3 are not interchangeable like
+:c:type:PyString
and :c:type:PyUnicode
are in Python 2. The following example
shows best practices with regards to :c:type:PyUnicode
, :c:type:PyString
,
and :c:type:PyBytes
. ::
@@ -94,10 +95,12 @@ and :c:type:PyBytes
. ::
long/int Unification
--------------------
-In Python 3.0, there is only one integer type. It is called :func:int
on the
-Python level, but actually corresponds to 2.x's :func:long
type. In the
-C-API, PyInt_*
functions are replaced by their PyLong_*
neighbors. The
-best course of action here is using the PyInt_*
functions aliased to
+Python 3 has only one integer type, :func:int
. But it actually
+corresponds to Python 2's :func:long
type--the :func:int
type
+used in Python 2 was removed. In the C-API, PyInt_*
functions
+are replaced by their PyLong_*
equivalents.
+
+The best course of action here is using the PyInt_*
functions aliased to
PyLong_*
found in :file:intobject.h
. The abstract PyNumber_*
APIs
can also be used in some cases. ::
@@ -120,10 +123,11 @@ can also be used in some cases. ::
Module initialization and state
===============================
-Python 3.0 has a revamped extension module initialization system. (See
-:pep:3121
.) Instead of storing module state in globals, they should be stored
-in an interpreter specific structure. Creating modules that act correctly in
-both 2.x and 3.0 is tricky. The following simple example demonstrates how. ::
+Python 3 has a revamped extension module initialization system. (See
+:pep:3121
.) Instead of storing module state in globals, they should
+be stored in an interpreter specific structure. Creating modules that
+act correctly in both Python 2 and Python 3 is tricky. The following
+simple example demonstrates how. ::
#include "Python.h"
@@ -209,10 +213,65 @@ both 2.x and 3.0 is tricky. The followi
}
+CObject replaced with Capsule
+=============================
+
+The :c:type:Capsule
object was introduced in Python 3.1 and 2.7 to replace
+:c:type:CObject
. CObjects were useful,
+but the :c:type: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.
+:c:type: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 :c:type:Capsule
. If you need to support Python 3.0,
+or versions of Python earlier than 2.7,
+you'll have to support both CObjects and Capsules.
+(Note that Python 3.0 is no longer supported, and it is not recommended
+for production use.)
+
+The following example header file :file:capsulethunk.h
may
+solve the problem for you. Simply write your code against the
+:c:type:Capsule
API and include this header file after
+:file:Python.h
. Your code will automatically use Capsules
+in versions of Python with Capsules, and switch to CObjects
+when Capsules are unavailable.
+
+:file:capsulethunk.h
simulates Capsules using CObjects. However,
+:c:type:CObject
provides no place to store the capsule's "name". As a
+result the simulated :c:type:Capsule
objects created by :file:capsulethunk.h
+behave slightly differently from real Capsules. Specifically:
+
- returns failure. (Since there's no way to store a name
- in a CObject, noisy failure of :c:func:
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
=============
If you are writing a new extension module, you might consider Cython[](#l1.167) <http://www.cython.org>
_. It translates a Python-like language to C. The
-extension modules it creates are compatible with Python 3.x and 2.x.
+extension modules it creates are compatible with Python 3 and Python 2.
new file mode 100644 --- /dev/null +++ b/Doc/includes/capsulethunk.h @@ -0,0 +1,134 @@ +#ifndef __CAPSULETHUNK_H +#define __CAPSULETHUNK_H + +#if ( (PY_VERSION_HEX < 0x02070000) [](#l2.8)
|| ((PY_VERSION_HEX >= 0x03000000) \[](#l2.9)
&& (PY_VERSION_HEX < 0x03010000)) )[](#l2.10)
+ +#define __PyCapsule_GetField(capsule, field, default_value) [](#l2.12)
- ( PyCapsule_CheckExact(capsule) [](#l2.13)
? (((PyCObject *)capsule)->field) \[](#l2.14)
: (default_value) \[](#l2.15)
- ) [](#l2.16)
+ +#define __PyCapsule_SetField(capsule, field, value) [](#l2.18)
- ( PyCapsule_CheckExact(capsule) [](#l2.19)
? (((PyCObject *)capsule)->field = value), 1 \[](#l2.20)
: 0 \[](#l2.21)
- ) [](#l2.22)
+ + +#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) [](#l2.31)
+ + +#define PyCapsule_GetPointer(capsule, name) [](#l2.35)
+ +/* Don't call PyCObject_SetPointer here, it fails if there's a destructor */ +#define PyCapsule_SetPointer(capsule, pointer) [](#l2.39)
+ + +#define PyCapsule_GetDestructor(capsule) [](#l2.43)
+ +#define PyCapsule_SetDestructor(capsule, dtor) [](#l2.46)
- */ +#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");[](#l2.61)
- return 1;
+} + + + +#define PyCapsule_GetContext(capsule) [](#l2.67)
+ +#define PyCapsule_SetContext(capsule, context) [](#l2.70)
+ + +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);
- trace = name_dup;
- while (trace) {
char *dot = strchr(trace, '.');[](#l2.91)
if (dot) {[](#l2.92)
*dot++ = '\0';[](#l2.93)
}[](#l2.94)
if (object == NULL) {[](#l2.96)
if (no_block) {[](#l2.97)
object = PyImport_ImportModuleNoBlock(trace);[](#l2.98)
} else {[](#l2.99)
object = PyImport_ImportModule(trace);[](#l2.100)
if (!object) {[](#l2.101)
PyErr_Format(PyExc_ImportError,[](#l2.102)
"PyCapsule_Import could not "[](#l2.103)
"import module \"%s\"", trace);[](#l2.104)
}[](#l2.105)
}[](#l2.106)
} else {[](#l2.107)
PyObject *object2 = PyObject_GetAttrString(object, trace);[](#l2.108)
Py_DECREF(object);[](#l2.109)
object = object2;[](#l2.110)
}[](#l2.111)
if (!object) {[](#l2.112)
goto EXIT;[](#l2.113)
}[](#l2.114)
- if (PyCObject_Check(object)) {
PyCObject *cobject = (PyCObject *)object;[](#l2.120)
return_value = cobject->cobject;[](#l2.121)
- } else {
PyErr_Format(PyExc_AttributeError,[](#l2.123)
"PyCapsule_Import \"%s\" is not valid",[](#l2.124)
name);[](#l2.125)
- }
+} + +#endif /* #if PY_VERSION_HEX < 0x02070000 / + +#endif / __CAPSULETHUNK_H */