Это полностью переписанная версия более раннего вопроса; Я думаю, что в первой версии опущены важные детали; этот предоставляет весь контекст.
У меня есть заголовок некоторого C++ API. API объявляет несколько классов следующим образом:
class Foo
{
public:
inline void Bar(void);
/* more inlines */
private:
inline Foo();
/* maybe more inline constructors */
}
Т.е. нет членов, все функции являются встроенными и открытыми, кроме конструкторов. Конструкторы являются частными, поэтому, насколько я понимаю C++, я не могу их назвать. Для создания этих объектов я должен использовать auto_ptr
s к ним:
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 "*")
Вот и все :) Спасибо всем!