Дизайн интерфейса C ++ вокруг границ разделяемой библиотеки - PullRequest
8 голосов
/ 03 августа 2011

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

Мое приложение использует STL, а моя общая библиотека также использует STL. Первая проблема заключается в том, что моя общая библиотека использует STL. Если я когда-нибудь добавлю в свое приложение более новую версию STL, но не буду перестраивать свою разделяемую библиотеку, поскольку в этом нет необходимости, у нас сразу же возникнут проблемы совместимости.

Моя первая мысль для решения этой проблемы - вообще не использовать STL в интерфейсе классов разделяемой библиотеки. Предположим, в моей библиотеке есть функция, которая берет строку и что-то с ней делает. Я бы сделал прототип функции похожим на:

void DoStuffWithStrings( char const* str );

вместо:

void DoStuffWithStrings( std::string const& str );

Для строк это, вероятно, будет хорошо в разных версиях STL, но недостатком является то, что мы переходим от std::string к char* и обратно к std::string, что, похоже, вызывает проблемы с производительностью.

Рекомендуется ли упаковка / распаковка необработанных типов в их аналоги STL? Это становится еще хуже, когда мы пытаемся сделать это с std::list, так как на самом деле нет «необработанного типа», о котором я знаю, что мы могли бы легко передать его как без выполнения какой-либо операции O (n) или аналогичной операции.

Какие конструкции лучше всего работают в этом сценарии? Каковы плюсы / минусы каждого?

Ответы [ 4 ]

3 голосов
/ 03 августа 2011

Один из плюсов подхода const char* заключается в том, что ваша библиотека также будет вызываться из C, и, следовательно, из множества других языков, также взаимодействующих с C (почти все). Одно это очень интересное предложение для продажи.

Однако, если вы пишете и поддерживаете обе библиотеки, и они будут использоваться только на C ++ (скажем, в течение следующих 5 лет), я бы не стал переживать за преобразование всего. std::string - это одно, std::vector или std::map не будут конвертировать так хорошо. Кроме того, сколько раз вы переходите на другую реализацию STL? И в этих случаях вы действительно «забудете» перестроить свою разделяемую библиотеку? Кроме того, вы по-прежнему можете писать / генерировать обертки в стиле C, если это действительно необходимо.

Заключение (предвзятое отношение к моему опыту в этом вопросе): если вам не нужен C, переходите к stl.

2 голосов
/ 03 августа 2011

Конечно, стандартная библиотека C ++ должна рассматриваться как часть C ++ ABI так же, как схема виртуальной таблицы или схема искажения имен. Кроме того, любые несовместимые изменения в ABI, скорее всего, будут влиять на неясные угловые случаи, а не на расположение std :: vector. Другими словами: если вы собираетесь создавать библиотеку C ++, не стесняйтесь использовать стандартные классы C ++.

1 голос
/ 03 августа 2011

Другая проблема может возникнуть, если библиотека использует кучу, отличную от приложения. Если это так или может быть, убедитесь, что библиотека владеет / управляет своей собственной памятью. Многочисленные кучи могут быть проблемой, когда библиотека использует другую c-библиотеку и, следовательно, другую malloc / free и, следовательно, другую кучу. http://msdn.microsoft.com/en-us/library/ms810466.aspx

0 голосов
/ 03 августа 2011

Многие API и общие библиотеки используют «непрозрачные» или универсальные указатели в качестве аргументов в функциях, чтобы избежать различий между версиями.

// this:
int MyFunc(char* Param1, int Param2, bool Param3);

// into this:
struct MyParams
{
  char* Param1;
  int Param2;
  bool Param3;
}

// "Params" its really "struct MyParams*"
int MyFunc(void* Params);

И иногда, если функция общей библиотеки имеет несколько аргументов, они заменяютсяна указатель ожидается, что taht будет указателем на массив, структуру или даже класс.

Это зависит от того, как вы собираетесь работать с вашей библиотекой, поскольку многие библиотеки используются как обычный C, даже есливы используете C ++.

...