Установить базу для объекта неопределенного размера

0

Я хотел бы недавно описать ситуацию, с которой я столкнулся, чтобы задать вопрос в каком-то контексте.

Я пишу оболочку Python C++. Базовым элементом Python является PyObject. Каждый объект в Python представляет собой PyObject + более необязательный материал.

То есть, первый sizeofPyObject) байты гарантированно заполняют поля PyObject, но различные объекты могут выделять дополнительную непрерывную память.

Выгода (причина?) Для этого заключается в том, что все может быть возвращено в PyObject.

Я пытаюсь обернуть такого зверя:

class CxxWrapper : PyObject {}

Скажем, я создаю void foo(PyObject* p) и вставляю foo в одну из таблиц функций-указателей времени исполнения Python.

Тогда среда выполнения вызовет эту функцию (по какой-либо причине), передав указатель на соответствующий PyObject.

Я хотел бы иметь возможность придать этот результат прямо к соответствующему объекту CxxWrapper:

CxxWrapper* cxxw = static_cast<CxxWrapper>p;

Однако я не вижу никакого способа заставить этот механизм работать. Потому что я не вижу способа установить базовый объект в какой-то PyObjectPlusExtra.

Есть какой-либо способ сделать это? А если нет, то каково ограничение C++?

  • 0
    Вы определенно можете объявить некоторые классы, базовым классом или первым членом которых является PyObject, а затем последуют любые другие члены.
  • 0
    CxxWrapper* cxxw = static_cast<CxxWrapper*>(p);
Показать ещё 3 комментария
Теги:
c++11
base-class
memory-management

2 ответа

0
Лучший ответ

Плохо сформировавшийся вопрос. С 20:20 задним числом, вот что происходит:

Я имею дело с C Library использует схему наследования типа C, т.е.

struct CBase{
    int a,b;
}

struct CDer{
    CBase ab;
    int c;
}

Я планирую свой C++ код таким образом:

class CxxBase : CBase

Так что, если я получаю указатель от C, я могу привести к эквивалентному объекту CxxBase и наоборот.

Проблема в том, что C++ управляет наследованием в значительной степени аналогично тому, как это показано на примере C. Финал: Der: Base будет хранить базу, а затем Der, а затем конечный объект в смежной памяти.

Таким образом, невозможно выполнить этот союз. И CDer, и CxxDer будут неизвестного размера.

Требуется другой метод, например, предложение Барри.

Тем не менее, это связано с достаточно дорогостоящим поиском.

Я не вижу решения лучше, чем существующее в проекте, над которым я работаю:

struct Bridge {
    CObj cob;
    CxxObj* p_cxxob;
}

const CxxObj& to_cxx(CObj* cob) { return *(cob->p_cxxob); }
1

Это неправильный способ сделать это, поскольку вы никогда не сможете построить свой объект! Вместо этого вы можете определить карту между PyObject и вашими объектами:

std::unordered_map<PyObject*, CxxStff> stuff;

void foo(PyObject* o) {
    CxxStuff& extra = stuff[o];
    // etc
} 

Поместите все, что захотите, в этот дополнительный класс, и вам будет хорошо.

  • 0
    Не видел тэг c ++ 11.
  • 0
    Спасибо, я не рассматривал этот подход. Это выглядит довольно дорого, хотя я не знаю, какова стоимость типизации базы-> производной.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню