C/C++ API puzzle

Это полностью переписанная версия более раннего вопроса; Я думаю, что в первой версии опущены важные детали; этот предоставляет весь контекст.

У меня есть заголовок некоторого C++ API. API объявляет несколько классов следующим образом:

class Foo
{
public:
    inline void Bar(void);
    /* more inlines */
private:
    inline Foo();
    /* maybe more inline constructors */
}

Т.е. нет членов, все функции являются встроенными и открытыми, кроме конструкторов. Конструкторы являются частными, поэтому, насколько я понимаю C++, я не могу их назвать. Для создания этих объектов я должен использовать auto_ptrs к ним:

class FooAutoPtr : public std::auto_ptr 
{
public:
    inline FooAutoPtr();
    /* one for each Foo constructors */
}

API также имеет второй набор функций, подобных этому:

void Foo_Bar(void *self);
Foo* Foo_Constructor();

Давайте назовем их основные функции, потому что это символы, фактически экспортированные из ведущего приложения. Не классы C++.

Основные функции имеют связь С (т.е.они объявлены как extern "C"), но они объявлены как принимающие и возвращающие типы C++ (например, они могут взять ссылку: Foo &foo). Наконец, заголовок содержит реализацию встроенных функций классов C++. Все эти функции делают то же самое: они называют основные функции. Например, конструктор FooAutoPtr выглядит следующим образом:

inline FooAutoPtr::FooAutoPtr()
{
   reset(Foo_Constructor());
}

Насколько я понимаю, код получает некоторый объект, который должен быть указателем на Foo из ведущего приложения, и изменяет auto_ptr на этот объект. Но для разработчика это выглядит так, как будто это был настоящий указатель на Foo. И вызов Foo::Bar() выглядит следующим образом:

inline Foo::Bar()
{
    Foo_Bar(this);
}

Это относится ко всем классам и методам C++. Умный, да?

Не мог бы кто-нибудь объяснить, что все это значит? :) Это не настоящий C++ API, не так ли? Для меня это больше похоже на тонкую оболочку C++ поверх C API. Если да, то Могу ли я пересмотреть основные функции, чтобы потерять биты C++? Я понимаю, как написать Обертку C вокруг C++ (на самом деле, я уже писал ее), но, если возможно, я бы предпочел потерять оболочку и использовать функции напрямую. Но как я могу потерять материал C++?

Например, может быть функция со ссылками:

Bar& Foo_GetBar(void* self, const Baz& baz, int& i);

Прямо сейчас я вызываю ее из своей оболочки C++ следующим образом:

typedef struct bar bar_t; /* and others */
/*...*/
bar_t*
foo_get_bar(foo_t* foo, baz_t* baz, int* i)
{
    return (bar_t*) &Foo_GetBar(foo, *(Baz*)baz, *i);
}

, и она работает (понятия не имею, как). Но я бы предпочел, чтобы это было переоценено следующим образом:

/* type? */ Foo_GetBar(foo_t*, /* type? /*, /* type? */);

UPDATE: Я нашел интересную вещь, которая подтверждает ответ Нила. Это код в Common Lisp, который использует тот же API. (Естественно, он должен использовать часть C.) И, из того, что я могу (едва) прочитать в источнике, автор просто использовал указатели вместо ссылок. Вот фрагмент из кода, который преобразует объявления C++ в Lisp:

;; use * instead of & - we're not interested in C++ details
line (regex-replace-all "&" line "*")

Вот и все :) Спасибо всем!

6
задан Community 23 May 2017 в 11:48
поделиться