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

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

Я пишу оболочку 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;
</cxxwrapper>

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

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

2 ответа

Плохо сформировавшийся вопрос. С 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); }


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

std::unordered_map<pyobject*, cxxstff=""> stuff;

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

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

licensed under cc by-sa 3.0 with attribution.