Пазл C / C ++ API - PullRequest
       21

Пазл C / C ++ API

6 голосов
/ 26 января 2012

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

У меня есть заголовок некоторого 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<Foo> 
{
public:
    inline FooAutoPtr();
    /* one for each Foo constructors */
}

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

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

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

Основные функции имеют связь 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? */);

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

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

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

Ответы [ 2 ]

4 голосов
/ 26 января 2012

Теоретически, детали того, как компилятор обрабатывает ссылку в объявлении C-linkage, являются неуказанными деталями реализации. Однако многие компиляторы рассматривают его как указатель. Поэтому, если заголовок библиотеки C ++ импортирует Bar& Foo_GetBar(void* self, const Baz& baz, int& i);, вы можете попробовать импортировать его в заголовок C как bar_t* Foo_GetBar(foo_t* self, const baz_t* baz, int* i);, и он может просто работать.

1 голос
/ 26 января 2012
#define & *    // convert references into pointers.

Стоп. Правильно. Там. Это была шутка, а не попытка узнать, сколько отрицательных голосов можно накопить за один ответ.

Но подход переписать файл заголовка, чтобы заменить ссылки указателями, безусловно, должен работать. Поскольку это функции C, нет необходимости беспокоиться об именах, и мне еще предстоит увидеть компилятор, который не реализует ссылки как указатели. (Есть ли другой возможный способ?)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...