139 lines
3.8 KiB
Plaintext
139 lines
3.8 KiB
Plaintext
|
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:
|