Наследование в расширении Python C ++ - PullRequest
3 голосов
/ 04 февраля 2010

У меня есть библиотека c ++, которая должна взаимодействовать с подключенными модулями Python. Коммуникация предполагает реализацию Python некоторого интерфейса обратного вызова c ++.

Я уже читал о написании расширений, но не знаю, как развивать наследование.

Итак, кое-что о: C ++:

class Broadcast
{
   void set(Listener *){...
}

class Listener
{
    void notify(Broadcast* owner) = 0;
}

Мне нужно что-то вроде в Python:

class ListenerImpl(Listener):
    ...
    def notify(self, owner):
        ...

Обратите внимание, я не хочу использовать Boost.

Ответы [ 2 ]

6 голосов
/ 06 ноября 2016

Поскольку мне пришлось реализовать одиночное наследование как часть Python C-API в моем проекте, я создал короткий пример здесь . Я отметил важные утверждения в коде.

Хитрость заключается в наследовании базовой структуры в верхней части структуры подкласса (пропустите оператор PyObject_HEAD).

/* OBJECT */
typedef struct {
      MyPy_BaseClass super; // <----- PUTTING THIS FIRST INHERITS THE BASE PYTHON CLASS!!!
      // Own variables:
      // e.g int x = 0;
} MyPy_InheritanceClass;

Также не забудьте указать базовый тип для типа подкласса. Для этого есть флаг (см. /* tp_base */).

  static PyTypeObject MyPy_InheritanceClass_Type = {
    PyVarObject_HEAD_INIT(NULL, 0)
    "MyPy_InheritanceClass",          /* tp_name */
    sizeof(MyPy_InheritanceClass),    /* tp_basicsize */
    0,                         /* tp_itemsize */
    (destructor)MyPy_InheritanceClass_dealloc, /* tp_dealloc */
    0,                         /* tp_print */
    0,                         /* tp_getattr */
    0,                         /* tp_setattr */
    0,                         /* tp_reserved */
    0,                         /* tp_repr */
    0,                         /* tp_as_number */
    0,                         /* tp_as_sequence */
    0,                         /* tp_as_mapping */
    0,                         /* tp_hash  */
    0,                         /* tp_call */
    0,                         /* tp_str */
    0,                         /* tp_getattro */
    0,                         /* tp_setattro */
    0,                         /* tp_as_buffer */
    Py_TPFLAGS_DEFAULT |
    Py_TPFLAGS_BASETYPE,       /* tp_flags */ 
    "MyPy_InheritanceClass",   /* tp_doc */
    0,                         /* tp_traverse */
    0,                         /* tp_clear */
    0,                         /* tp_richcompare */
    0,                         /* tp_weaklistoffset */
    0,                         /* tp_iter */
    0,                         /* tp_iternext */
    MyPy_InheritanceClass_methods,    /* tp_methods */
    0,                         /* tp_members */
    0,                         /* tp_getset */
    &MyPy_BaseClass_Type,      /* tp_base */ // <------ GIVE THE BASE_CLASS TYPE
    0,                         /* tp_dict */
    0,                         /* tp_descr_get */
    0,                         /* tp_descr_set */
    0,                         /* tp_dictoffset */
    (initproc) MyPy_InheritanceClass_init, /* tp_init */
    0,                         /* tp_alloc */
    MyPy_InheritanceClass_new, /* tp_new */
};
5 голосов
/ 04 февраля 2010

Написание типов Python в C, которые являются наследуемыми, объясняется в PEP 253 . Это не так уж и отличается от написания обычного встроенного типа, как описано в Руководстве по расширению / встраиванию , но вы должны делать определенные вещи, такие как доступ к атрибутам, через API Python вместо прямого доступа к чему-либо.

Представление подклассов Python обратно в код C ++ немного утомительнее. Классы Python не будут подклассами C ++, поэтому вам нужен класс-оболочка C ++ (который наследуется от Listener), который содержит PyObject* для экземпляра подкласса Python и имеет метод notify, который переводит аргументы к объектам Python, вызывает метод notify PyObject* (используя, например, PyObject_CallMethod), переводит результат обратно в типы C ++ и возвращает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...