2014-09-15 7 views
1

Я хотел бы понять внутренности системы импорта Python, включая грубые пятна. В API Python C documentation, есть эта немногословная ссылка на один такое грубое место:Статическая инициализация с указателем на переменную extern

Это настолько важно, что мы собираемся взять верх его обособленно еще дальше:

PyObject_HEAD_INIT(NULL) 

Эта линия немного бородавка; что мы хотели бы написать это:

PyObject_HEAD_INIT(&PyType_Type) 

как тип объекта типа является «типа», но это не является строго в соответствии C и некоторые компилятор жалуются.

Почему это не строго соответствует C? Почему некоторые компиляторы принимают это без жалобы, а другие нет?

теперь я думаю, что следующий может ввести в заблуждение, переходите к «СОДЕРЖАТЕЛЬНОЙ EDIT»

Прокрутка о странице вниз есть то, что я считаю, является ключом. Эта цитата относится к инициализации другого члена структуры, но это похоже на ту же проблему, и на этот раз это объясняется.

Мы хотели бы просто присвоить это к tp_new слот, но мы не можем, ради портативность, на некоторых платформах или компиляторов, мы не можем статически инициализировать элемент структуры с функцией, определенной в другом C

Это все еще оставляет меня в замешательстве, отчасти из-за выбора слова «модуль». Я думаю, что вторая цитата означала, что статическая инициализация, основанная на вызовах функций в отдельных единицах компиляции, является нестандартным расширением. Я до сих пор не понимаю, почему это так. Это то, что происходит в первой цитате?

СУЩЕСТВЕННОМУ EDIT:

Использование PyObject_HEAD_INIT(NULL) рекомендуется идти на самом верху инициализации экземпляра PyTypeObject.

Определение PyTypeObject выглядит следующим образом:

typedef struct _typeobject { 
    PyObject_VAR_HEAD 
    const char *tp_name; /* For printing, in format "<module>.<name>" */ 
    Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */ 

    /* Methods to implement standard operations */ 

    destructor tp_dealloc; 

/*... lots more ... */ 

} PyTypeObject; 

PyObject_HEAD_INIT(NULL) макрос используется для инициализации вершины экземпляров PyTypeObject. Верхняя часть определения PyTypeObject создается макросом PyObject_VAR_HEAD. PyObject_VAR_HEAD является:

/* PyObject_VAR_HEAD defines the initial segment of all variable-size 
* container objects. These end with a declaration of an array with 1 
* element, but enough space is malloc'ed so that the array actually 
* has room for ob_size elements. Note that ob_size is an element count, 
* not necessarily a byte count. 
*/ 
#define PyObject_VAR_HEAD    \ 
    PyObject_HEAD      \ 
    Py_ssize_t ob_size; /* Number of items in variable part */ 
#define Py_INVALID_SIZE (Py_ssize_t)-1 

В свою очередь, PyObject_HEAD расширяется:

/* PyObject_HEAD defines the initial segment of every PyObject. */ 
#define PyObject_HEAD     \ 
    _PyObject_HEAD_EXTRA    \ 
    Py_ssize_t ob_refcnt;    \ 
    struct _typeobject *ob_type; 

_PyObject_HEAD_EXTRA используется только при отладке сборок и обычно расширяется до нуля. Элементами, инициализированными макросом PyObject_HEAD_INIT, являются ob_refcnt и ob_type.ob_type - это тот, который мы хотели бы инициализировать с помощью &PyType_Type, но нам сказали, что это нарушит стандарт C. ob_type указывает на _typeobject, который typedef'd является PyTypeObject (той же структурой, которую мы пытаемся инициализировать). Мы используем PyObject_HEAD_INIT макрос, который инициализирует эти два значения, расширяется так:

#define PyObject_HEAD_INIT(type)  \ 
    _PyObject_EXTRA_INIT    \ 
    1, type, 

Итак, мы начинаем подсчет ссылок на 1 и установив указатель члена на то, что в параметре типа. Документация Python говорит, что мы не можем установить параметр типа it по адресу PyType_Type, потому что это не строго стандарт C, поэтому мы соглашаемся на NULL.

PyType_Type указано в одной и той же части перевода несколькими строками ниже.

PyAPI_DATA(PyTypeObject) PyType_Type; /* built-in 'type' */ 

PyAPI_DATA определен в другом месте. Он имеет несколько условных определений.

#define PyAPI_DATA(RTYPE) extern __declspec(dllexport) RTYPE 
#define PyAPI_DATA(RTYPE) extern RTYPE 

Так документация API Python говорит, что мы хотели бы, чтобы инициализировать экземпляр PyTypeObject с указателем на ранее объявленной PyTypeObject, который был объявлен с экстерном классификатором. Что в С-стандарте нарушило бы?

Инициализация PyType_Type происходит в .c файле. Типичное расширение Python, который инициализирует PyTypeObject, как описано выше, будет динамически загружен код, который был составлен с этой инициализации:

PyTypeObject PyType_Type = { 
    PyVarObject_HEAD_INIT(&PyType_Type, 0) 
    "type",          /* tp_name */ 
    sizeof(PyHeapTypeObject),     /* tp_basicsize */ 
    sizeof(PyMemberDef),      /* tp_itemsize */ 
    (destructor)type_dealloc,     /* tp_dealloc */ 

/* ... lots more ... */ 
} 
+0

Каково определение PyObject_VAR_HEAD, для которого PyObject_HEAD_INIT (...) является инициализатором? –

+0

Я думаю, что это отклоняется от курса, но определение: #define PyObject_VAR_HEAD \ PyObject_HEAD \ Py_ssize_t ob_size; Я могу туннелировать через макросы и добавить к ней через несколько минут. – Praxeolitic

+0

«Я думаю, что это отклоняется от курса». Ну, тогда вам не хватает базового понимания. Что вам нужно знать здесь, это тип того, что инициализирует '& PyType_Type' (или NULL). Итак, вы должны опубликовать определение PyObject_HEAD.И если это определено в терминах еще одного макроса, опубликуйте его определение и так далее. Если вы действительно не хотите никакой помощи. –

ответ

1
PyObject_HEAD_INIT(&PyType_Type) 

производит

1, &PyType_Type 

, который инициализирует полей

Py_ssize_t ob_refcnt; 
struct _typeobject *ob_type; 

PyType_Type определяется с помощью PyAPI_DATA(PyTypeObject) PyType_Type whi ch производит

extern PyTypeObject PyType_Type; 

возможно с квалификатором __declspec. PyTypeObject является ЬурейиМ для STRUCT _typeobject, поэтому мы имеем

extern struct _typeobject PyType_Type; 

так PyObject_HEAD_INIT(&PyType_Type) будет инициализировать struct _typeobject* ob_type поля с struct _typeobject* ... что, безусловно, действует C, так что я не понимаю, почему они говорят, что это не ,

0

Я пришел к объяснению этого в другом месте исходного кода Python.

/* We link this module statically for convenience. If compiled as a shared 
    library instead, some compilers don't allow addresses of Python objects 
    defined in other libraries to be used in static initializers here. The 
    DEFERRED_ADDRESS macro is used to tag the slots where such addresses 
    appear; the module init function must fill in the tagged slots at runtime. 
    The argument is for documentation -- the macro ignores it. 
*/ 
#define DEFERRED_ADDRESS(ADDR) 0 

И тогда макрос используется там, где NULL появляется в верхней части ОП.

PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) 

 Смежные вопросы

  • Нет связанных вопросов^_^