diff options
author | Benjamin Peterson <benjamin@python.org> | 2008-09-28 02:06:32 (GMT) |
---|---|---|
committer | Benjamin Peterson <benjamin@python.org> | 2008-09-28 02:06:32 (GMT) |
commit | e9bbc8b2571b0f39da7810e9e6fc5511691ab7ac (patch) | |
tree | 9cfc2f7830bd170b48f3346503551c74d5627274 /Doc/howto | |
parent | d61de7f18db0eb9763a046f547053ccc59f2bfc5 (diff) | |
download | cpython-e9bbc8b2571b0f39da7810e9e6fc5511691ab7ac.zip cpython-e9bbc8b2571b0f39da7810e9e6fc5511691ab7ac.tar.gz cpython-e9bbc8b2571b0f39da7810e9e6fc5511691ab7ac.tar.bz2 |
Devil merge!
Merged revisions 66561,66564,66580,66610,66614,66618,66624-66625,66628-66629,66643,66645,66660-66665 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r66561 | benjamin.peterson | 2008-09-22 17:13:29 -0500 (Mon, 22 Sep 2008) | 1 line
clean up docs for platform's linux_distribution and dist functions
........
r66564 | benjamin.peterson | 2008-09-23 08:32:46 -0500 (Tue, 23 Sep 2008) | 1 line
mention how to override boolean evaluation
........
r66580 | georg.brandl | 2008-09-24 04:47:55 -0500 (Wed, 24 Sep 2008) | 2 lines
Indentation normalization.
........
r66610 | andrew.kuchling | 2008-09-24 12:27:55 -0500 (Wed, 24 Sep 2008) | 1 line
Improve wording
........
r66614 | benjamin.peterson | 2008-09-24 17:11:59 -0500 (Wed, 24 Sep 2008) | 4 lines
#3950 fix missing scale factors in turtle.py
reviewers: Georg, Benjamin
........
r66618 | benjamin.peterson | 2008-09-25 15:35:45 -0500 (Thu, 25 Sep 2008) | 1 line
add a NEWs entry for r66614
........
r66624 | raymond.hettinger | 2008-09-25 18:31:52 -0500 (Thu, 25 Sep 2008) | 1 line
Fix namedtuple bug reported by Glenn Linderman. Template did not form correctly if the field names were input in Unicode.
........
r66625 | benjamin.peterson | 2008-09-25 21:58:36 -0500 (Thu, 25 Sep 2008) | 1 line
add the beginnings of a C-API 2 -> 3 porting guide
........
r66628 | benjamin.peterson | 2008-09-26 15:52:06 -0500 (Fri, 26 Sep 2008) | 1 line
add an 'other options' section
........
r66629 | georg.brandl | 2008-09-26 16:15:21 -0500 (Fri, 26 Sep 2008) | 2 lines
typos.
........
r66643 | andrew.kuchling | 2008-09-27 09:12:33 -0500 (Sat, 27 Sep 2008) | 1 line
Add a last bunch of items
........
r66645 | benjamin.peterson | 2008-09-27 11:23:55 -0500 (Sat, 27 Sep 2008) | 1 line
2to3's api should be considered unstable
........
r66660 | andrew.kuchling | 2008-09-27 17:54:08 -0500 (Sat, 27 Sep 2008) | 1 line
#3510: future-proof text
........
r66661 | benjamin.peterson | 2008-09-27 18:28:43 -0500 (Sat, 27 Sep 2008) | 1 line
clarify a few things
........
r66662 | andrew.kuchling | 2008-09-27 19:15:27 -0500 (Sat, 27 Sep 2008) | 1 line
#1579477: mention necessity to flush output before exec'ing
........
r66663 | andrew.kuchling | 2008-09-27 20:08:47 -0500 (Sat, 27 Sep 2008) | 1 line
#1415508: Document two functions
........
r66664 | benjamin.peterson | 2008-09-27 20:51:36 -0500 (Sat, 27 Sep 2008) | 1 line
better grammar
........
r66665 | benjamin.peterson | 2008-09-27 20:53:29 -0500 (Sat, 27 Sep 2008) | 1 line
note the 2to3 -d could be useful for other refactoring
........
Diffstat (limited to 'Doc/howto')
-rw-r--r-- | Doc/howto/cporting.rst | 216 | ||||
-rw-r--r-- | Doc/howto/index.rst | 1 |
2 files changed, 217 insertions, 0 deletions
diff --git a/Doc/howto/cporting.rst b/Doc/howto/cporting.rst new file mode 100644 index 0000000..3451f5c --- /dev/null +++ b/Doc/howto/cporting.rst @@ -0,0 +1,216 @@ +.. highlightlang:: c + +******************************** +Porting Extension Modules to 3.0 +******************************** + +: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. + + +Conditional compilation +======================= + +The easiest way to compile only some code for 3.0 is to check if +:cmacro:`PY_MAJOR_VERSION` is greater than or equal to 3. :: + + #if PY_MAJOR_VERSION >= 3 + #define IS_PY3K + #endif + +API functions that are not present can be aliased to their equivalents within +conditional blocks. + + +Changes to Object APIs +====================== + +Python 3.0 merged together some types with similar functions while cleanly +separating others. + + +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, +:file:`bytesobject.h`, mapping ``PyBytes`` names to ``PyString`` ones. For best +compatibility with 3.0, :ctype:`PyUnicode` should be used for textual data and +:ctype:`PyBytes` for binary data. It's also important to remember that +:ctype:`PyBytes` and :ctype:`PyUnicode` in 3.0 are not interchangeable like +:ctype:`PyString` and :ctype:`PyString` are in 2.x. The following example shows +best practices with regards to :ctype:`PyUnicode`, :ctype:`PyString`, and +:ctype:`PyBytes`. :: + + #include "stdlib.h" + #include "Python.h" + #include "bytesobject.h" + + /* text example */ + static PyObject * + say_hello(PyObject *self, PyObject *args) { + PyObject *name, *result; + + if (!PyArg_ParseTuple(args, "U:say_hello", &name)) + return NULL; + + result = PyUnicode_FromFormat("Hello, %S!", name); + return result; + } + + /* just a forward */ + static char * do_encode(PyObject *); + + /* bytes example */ + static PyObject * + encode_object(PyObject *self, PyObject *args) { + char *encoded; + PyObject *result, *myobj; + + if (!PyArg_ParseTuple(args, "O:encode_object", &myobj)) + return NULL; + + encoded = do_encode(myobj); + if (encoded == NULL) + return NULL; + result = PyBytes_FromString(encoded); + free(encoded); + return result; + } + + +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 +``PyLong_*`` found in :file:`intobject.h`. The the abstract ``PyNumber_*`` APIs +can also be used in some cases. :: + + #include "Python.h" + #include "intobject.h" + + static PyObject * + add_ints(PyObject *self, PyObject *args) { + int one, two; + PyObject *result; + + if (!PyArg_ParseTuple(args, "ii:add_ints", &one, &two)) + return NULL; + + return PyInt_FromLong(one + two); + } + + + +Module initialization and state +=============================== + +Python 3.0 has a revamped extension module initialization system. (See PEP +: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. :: + + #include "Python.h" + + struct module_state { + PyObject *error; + }; + + #if PY_MAJOR_VERSION >= 3 + #define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) + #else + #define GETSTATE(m) (&_state) + static struct module_state _state; + #endif + + static PyObject * + error_out(PyObject *m) { + struct module_state *st = GETSTATE(m); + PyErr_SetString(st->error, "something bad happened"); + return NULL; + } + + static PyMethodDef myextension_methods[] = { + {"error_out", (PyCFunction)error_out, METH_NOARGS, NULL}, + {NULL, NULL} + }; + + #if PY_MAJOR_VERSION >= 3 + + static int myextension_traverse(PyObject *m, visitproc visit, void *arg) { + Py_VISIT(GETSTATE(m)->error); + return 0; + } + + static int myextension_clear(PyObject *m) { + Py_CLEAR(GETSTATE(m)->error); + return 0; + } + + + static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "myextension", + NULL, + sizeof(struct module_state), + myextension_methods, + NULL, + myextension_traverse, + myextension_clear, + NULL + }; + + #define INITERROR return NULL + + PyObject * + PyInit_myextension(void) + + #else + #define INITERROR return + + void + initmyextension(void) + #endif + { + #if PY_MAJOR_VERSION >= 3 + PyObject *module = PyModule_Create(&moduledef); + #else + PyObject *module = Py_InitModule("myextension", myextension_methods); + #endif + + if (module == NULL) + INITERROR; + struct module_state *st = GETSTATE(module); + + st->error = PyErr_NewException("myextension.Error", NULL, NULL); + if (st->error == NULL) { + Py_DECREF(module); + INITERROR; + } + + #if PY_MAJOR_VERSION >= 3 + return module; + #endif + } + + +Other options +============= + +If you are writing a new extension module, you might consider `Cython +<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. + diff --git a/Doc/howto/index.rst b/Doc/howto/index.rst index 5a1f397..7d64688 100644 --- a/Doc/howto/index.rst +++ b/Doc/howto/index.rst @@ -14,6 +14,7 @@ Currently, the HOWTOs are: :maxdepth: 1 advocacy.rst + cporting.rst curses.rst doanddont.rst functional.rst |