[Python-3000] PyObject_HEAD_INIT

M.-A. Lemburg mal at egenix.com
Fri Nov 21 18:53:52 CET 2008


On 2008-11-21 18:36, Adam Olsen wrote:
> On Fri, Nov 21, 2008 at 7:14 AM, M.-A. Lemburg <mal at egenix.com> wrote:
>> On 2008-11-20 20:34, Roger Binns wrote:
>>> M.-A. Lemburg wrote:
>>>> Whether you write:
>>>> {PyObject_HEAD_INIT(0), 0, ...
>>>> or
>>>> {PyVarObject_HEAD_INIT(0, 0), ...
>>>> for your type definition doesn't really make much difference.
>>> Actually in Py 3 it does.  If you use the former (which is how Py 2 does
>>> it) then you get serious compiler warnings due to misaligned fields in
>>> Py 3 and presumably even worse if run the code.
>> You might get warnings (esp. from GCC), but I have yet to see a compiler
>> that doesn't map the above to the same memory.
>>
>> After all, Python 2 has been using this layout for years without any
>> compiler warnings or segfaults because of this.
> 
> The definition of PyObject_HEAD_INIT and PyVarObject_HEAD_INIT
> changed.  We've gone from a series of common fields to a single struct
> containing the fields.  With the series of fields using
> PyObject_HEAD_INIT followed by a size was perfectly correct, but with
> a struct it's gibberish.

Sigh...

Python 2.5:
-----------

(gdb) print PyUnicode_Type
$2 = {ob_refcnt = 1, ob_type = 0x6404c0, ob_size = 0, tp_name = 0x505972 "unicode",
  tp_basicsize = 48, tp_itemsize = 0, tp_dealloc = 0x470500 <unicode_dealloc>,
tp_print = 0,
  tp_getattr = 0, tp_setattr = 0, tp_compare = 0, tp_repr = 0x4746c0 <unicode_repr>,
  tp_as_number = 0x644f60, tp_as_sequence = 0x644f00, tp_as_mapping = 0x644ee0,
...

(gdb) print &PyUnicode_Type.tp_name
$3 = (const char **) 0x642758
(gdb) print &PyUnicode_Type.ob_refcnt
$4 = (Py_ssize_t *) 0x642740

Python 3.0:
-----------

(gdb) print PyUnicode_Type
$1 = {ob_base = {ob_base = {ob_refcnt = 1, ob_type = 0x733940}, ob_size = 0},
  tp_name = 0x4f52e9 "str", tp_basicsize = 56, tp_itemsize = 0,
  tp_dealloc = 0x42af80 <unicode_dealloc>, tp_print = 0, tp_getattr = 0,
tp_setattr = 0,
  tp_compare = 0, tp_repr = 0x431ca0 <unicode_repr>, tp_as_number = 0x736420,
...

(gdb) print &PyUnicode_Type.tp_name
$3 = (const char **) 0x735bf8
(gdb) print &PyUnicode_Type.ob_base
$4 = (PyVarObject *) 0x735be0

In both cases, the fields are 24 bytes apart (on my 64-bit machine).

Yes, it's a different way of writing and accessing the resp. fields.
No, it's not a different memory layout.
Yes, this is binary compatible.
No, this is not going to help you, since the rest of Python 3 is not ;-)

Fortunately, you only rarely have to access the fields in question
directly in extensions. And Python 3.0 and 2.6 also add a few macros
for abstracting this:

#define Py_REFCNT(ob) ...
#define Py_TYPE(ob) ...
#define Py_SIZE(ob) ...

-- 
Marc-Andre Lemburg
eGenix.com

Professional Python Services directly from the Source  (#1, Nov 21 2008)
>>> Python/Zope Consulting and Support ...        http://www.egenix.com/
>>> mxODBC.Zope.Database.Adapter ...             http://zope.egenix.com/
>>> mxODBC, mxDateTime, mxTextTools ...        http://python.egenix.com/
________________________________________________________________________
2008-11-12: Released mxODBC.Connect 0.9.3      http://python.egenix.com/

:::: Try mxODBC.Zope.DA for Windows,Linux,Solaris,MacOSX for free ! ::::


   eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
    D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
           Registered at Amtsgericht Duesseldorf: HRB 46611


More information about the Python-3000 mailing list