Add PEP 3123.
This commit is contained in:
parent
a15817652d
commit
a20cd09644
|
@ -119,6 +119,7 @@ Index by Category
|
|||
S 3119 Introducing Abstract Base Classes GvR, Talin
|
||||
S 3120 Using UTF-8 as the default source encoding von Löwis
|
||||
S 3121 Module Initialization and finalization von Löwis
|
||||
S 3123 Making PyObject_HEAD conform to standard C von Löwis
|
||||
S 3141 A Type Hierarchy for Numbers Yasskin
|
||||
|
||||
Finished PEPs (done, implemented in Subversion)
|
||||
|
@ -480,6 +481,7 @@ Numerical Index
|
|||
S 3120 Using UTF-8 as the default source encoding von Löwis
|
||||
S 3121 Module Initialization and finalization von Löwis
|
||||
SR 3122 Delineation of the main module Cannon
|
||||
S 3123 Making PyObject_HEAD conform to standard C von Löwis
|
||||
S 3141 A Type Hierarchy for Numbers Yasskin
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
PEP: 3123
|
||||
Title: Making PyObject_HEAD conform to standard C
|
||||
Version: $Revision$
|
||||
Last-Modified: $Date$
|
||||
Author: Martin v. Löwis <martin@v.loewis.de>
|
||||
Status: Draft
|
||||
Type: Standards Track
|
||||
Content-Type: text/x-rst
|
||||
Created: 27-Apr-2007
|
||||
Python-Version: 3.0
|
||||
Post-History:
|
||||
|
||||
Abstract
|
||||
========
|
||||
|
||||
Python currently relies on undefined C behavior, with its
|
||||
usage of PyObject_HEAD. This PEP proposes to change that
|
||||
into standard C.
|
||||
|
||||
Rationale
|
||||
=========
|
||||
|
||||
Standard C defines that an object must be accessed only through a
|
||||
pointer of its type, and that all other accesses are undefined
|
||||
behavior, with a few exceptions. In particular, the following
|
||||
code has undefined behavior::
|
||||
|
||||
struct FooObject{
|
||||
PyObject_HEAD
|
||||
int data;
|
||||
};
|
||||
|
||||
PyObject *foo(struct FooObject*f){
|
||||
return (PyObject*)f;
|
||||
}
|
||||
|
||||
int bar(){
|
||||
struct FooObject *f = malloc(sizeof(struct FooObject));
|
||||
struct PyObject *o = foo(f);
|
||||
f->ob_refcnt = 0;
|
||||
o->ob_refcnt = 1;
|
||||
return f->ob_refcnt;
|
||||
}
|
||||
|
||||
The problem here is that the storage is both accessed as
|
||||
if it where struct PyObject, and as struct FooObject.
|
||||
|
||||
Historically, compilers did not cause any problems with this
|
||||
code. However, modern compiler use that clause as an
|
||||
optimization opportunity, finding that f->ob_refcnt and
|
||||
o->ob_refcnt cannot possibly refer to the same memory, and
|
||||
that therefore the function should return 0, without having
|
||||
to fetch the value of ob_refcnt at all in the return
|
||||
statement. For GCC, Python now uses -fno-strict-aliasing
|
||||
to work around that problem; with other compilers, it
|
||||
may just see undefined behavior. Even with GCC, using
|
||||
-fno-strict-aliasing may pessimize the generated code
|
||||
unnecessarily.
|
||||
|
||||
Specification
|
||||
=============
|
||||
|
||||
Standard C has one specific exception to its aliasing rules precisely
|
||||
designed to support the case of Python: a value of a struct type may
|
||||
also be accessed through a pointer to the first field. E.g. if a
|
||||
struct starts with an int, the struct\* may also be cast to an int\*,
|
||||
allowing to write int values into the first field.
|
||||
|
||||
For Python, PyObject_HEAD and PyObject_VAR_HEAD will be changed
|
||||
to not list all fields anymore, but list a single field of type
|
||||
PyObject/PyVarObject::
|
||||
|
||||
typedef struct _object{
|
||||
_PyObject_HEAD_EXTRA
|
||||
Py_ssize_t ob_refcnt;
|
||||
struct _typeobject *ob_type;
|
||||
}PyObject;
|
||||
|
||||
typedef struct {
|
||||
PyObject ob_base;
|
||||
Py_ssize_t ob_size;
|
||||
} PyVarObject;
|
||||
|
||||
#define PyObject_HEAD PyObject ob_base;
|
||||
#define PyObject_VAR_HEAD PyVarObject ob_base;
|
||||
|
||||
Types defined as fixed-size structure will then include PyObject
|
||||
as its first field; variable-sized objects PyVarObject. E.g.::
|
||||
|
||||
typedef struct{
|
||||
PyObject ob_base;
|
||||
PyObject *start, *stop, *step;
|
||||
} PySliceObject;
|
||||
|
||||
typedef struct{
|
||||
PyVarObject ob_base;
|
||||
PyObject **ob_item;
|
||||
Py_ssize_t allocated;
|
||||
} PyListObject;
|
||||
|
||||
The above definitions of PyObject_HEAD is normative, so extension
|
||||
authors MAY either use the macro, or put the ob_base field explicitly
|
||||
into their structs.
|
||||
|
||||
As a convention, the base field SHOULD be called ob_base. However, all
|
||||
accesses to ob_refcnt and ob_type MUST cast the object pointer to
|
||||
PyObject* (unless the pointer is already known to have that type), and
|
||||
SHOULD use the respective accessor macros. To simplify access to
|
||||
ob_type, a macro::
|
||||
|
||||
#define Py_Type(o) (((PyObject*)o)->ob_type)
|
||||
|
||||
is added.
|
||||
|
||||
Compatibility with Python 2.6
|
||||
=============================
|
||||
|
||||
To support modules that compile with both Python 2.6 and Python 3.0,
|
||||
the Py_Type macro is added to Python 2.6. The macros Py_INCREF
|
||||
and Py_DECREF will be changed to cast their argument to PyObject\*,
|
||||
so that module authors can also explicitly declare the ob_base
|
||||
field in modules designed for Python 2.6.
|
||||
|
||||
Copyright
|
||||
=========
|
||||
|
||||
This document has been placed in the public domain.
|
||||
|
||||
|
||||
|
||||
..
|
||||
Local Variables:
|
||||
mode: indented-text
|
||||
indent-tabs-mode: nil
|
||||
sentence-end-double-space: t
|
||||
fill-column: 70
|
||||
coding: utf-8
|
||||
End:
|
Loading…
Reference in New Issue