Скажем, у нас есть библиотека С++ с таким классом:
class TheClass {
public:
TheClass() { ... }
void magic() { ... }
private:
int x;
}
Типичное использование этого класса будет включать распределение стека:
TheClass object;
object.magic();
Нам нужно создать оболочку C для этого класса. Наиболее распространенный подход выглядит следующим образом:
struct TheClassH;
extern "C" struct TheClassH* create_the_class() {
return reinterpret_cast<struct TheClassH*>(new TheClass());
}
extern "C" void the_class_magic(struct TheClassH* self) {
reinterpret_cast<TheClass*>(self)->magic();
}
Однако это требует распределения кучи, что явно не желательно для такого небольшого класса.
Я ищу подход, позволяющий выделить стек из этого класса из C-кода. Вот о чем я могу думать:
struct TheClassW {
char space[SIZEOF_THECLASS];
}
void create_the_class(struct TheClassW* self) {
TheClass* cpp_self = reinterpret_cast<TheClass*>(self);
new(cpp_self) TheClass();
}
void the_class_magic(struct TheClassW* self) {
TheClass* cpp_self = reinterpret_cast<TheClass*>(self);
cpp_self->magic();
}
Трудно поместить реальное содержимое класса в поля структуры. Мы не можем просто включать заголовок С++, потому что C не понимает его, поэтому нам потребуется написать совместимые заголовки C. И это не всегда возможно. Я думаю, что C-библиотекам действительно не нужно заботиться о содержании структур.
Использование этой оболочки будет выглядеть следующим образом:
TheClassW object;
create_the_class(&object);
the_class_magic(&object);
Вопросы:
- Есть ли у этого подхода какие-либо опасности или недостатки?
- Есть ли альтернативный подход?
- Существуют ли существующие оболочки, которые используют этот подход?