Как мы можем правильно реализовать привязки Python к подклассам объектов C ++? - PullRequest
2 голосов
/ 16 июля 2010

У меня проблема с довольно сложным взаимодействием C ++ и Python, в котором, я надеюсь, сообщество может помочь мне. Если мое объяснение не имеет смысла, дайте мне знать в комментариях, и я постараюсь уточнить.

Наша база кода C ++ содержит родительские классы с именем «IODevice», которые являются родительскими для других классов, таких как «File» и «Socket» и так далее. Мы сделали это так, чтобы в большей части нашего кода мы могли работать в общем случае с объектами «IODevice», которые на самом деле могут быть файлами, сокетами или чем-то, что мы изначально создали. Все это прекрасно работает в коде C ++.

Мы начали создавать привязки Python для некоторых наших объектов. Мы не хотели изменять исходные классы «Файл» или «Сокет»; мы создали подклассы «FilePy» и «SocketPy» классов «File» и «Socket». Эти * Py классы содержат необходимый код привязки Python.

Вот здесь и начинается проблема. Допустим, у меня есть класс C ++ «InputProcessorPy», который имеет соответствующие привязки Python. Я хотел бы иметь возможность построить его в своем коде Python и передать ему объект «FilePy» или «SocketPy», из которого «InputProcessorPy» будет получать данные. Код привязки Python из «InputProcessorPy» выглядит следующим образом:

PyObject* InputProcessor::PyMake(PyObject* ignored, PyObject *args)
{
    PyObject* cD_py;
    IODevice* inputFile;

    if (!PyArg_ParseTuple(args, "O", &cD_py))
        return NULL;

    inputFile = (IODevice*) cD_py;
    inputFile->isReadable();
    printf("------>>>> Done\n");

    return (PyObject *) new CL_InputRenderer(*inputFile, InputProcessor::Type);
}

Если я запускаю этот код, я получаю ошибку сегментации при вызове метода isReadable () для inputFile, который на самом деле является методом базового класса IODevice.

Если вместо этого я сделаю это:

    ...
    FilePy* inputFile;
    ...
    inputFile = (FilePy*) cD_py;
    inputFile->isReadable();
    ...

В этом случае код работает нормально. Это, однако, нежелательно, так как предполагает, что мы передаем объект FilePy, что не будет иметь место; это может быть «SocketPy», «BufferPy», «StringPy» или любой другой вид подкласса «IODevice».

Кажется, что процесс связывания Python каким-то образом несовместим со структурой наследования классов C ++, которую мы пытаемся использовать. Кто-нибудь пытался решить такую ​​проблему раньше? Правильно ли мы делаем наследование C ++ или должны делать что-то другое в наших привязках Python, чтобы эта работа работала?

1 Ответ

4 голосов
/ 16 июля 2010

Ваши типы FilePy и IODevice являются производными от PyObject? В противном случае компилятор C ++ будет интерпретировать:

inputFile = (IODevice*) cD_py;

как:

inputFile = reinterpret_cast<IODevice*> (cD_py);

а не то, что вы ожидали:

inputFile = dynamic_cast<IODevice*> (cD_py);

Если переданный фактический тип не является PyObject или IODevice не связан с PyObject через наследование, компилятор C ++ или среда выполнения не смогут узнать, как найти надлежащий vtable.

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