Связывание: статическое против динамического - PullRequest
7 голосов
/ 16 января 2011

В моем приложении у меня есть 3 основных части:

  • Exe: исполняемый файл
  • Lib_A: библиотека содержит класс синглтона и базовый класс для некоторых вычислений, которые будут использоваться в синглтоне класс
  • Lib_B: библиотека содержит ряд классов, полученных из базы в Lib_A

Причина, по которой у меня есть производные классы в Lib_B, заключается в том, что я хотел бы скомпилировать Lib_B во время выполнения из Exe. Мне нужно генерировать производные классы во время расчетов, не прерывая всю систему. Это слишком важно для меня. Это означает, что изначально я могу сказать, что Lib_B1 динамически загружен, а также я могу скомпилировать другие версии Lib_B как Lib_B2, Lib_B3, Lib_B4 и т. Д. И загружать их динамически. Все библиотеки Lib_Bx будут иметь функции точки входа для экспорта в них классов.

Итак, принимая во внимание следующие факты:

  • Во время выполнения будет различное количество файлов, совместно использующих одну и ту же библиотеку Lib_A.
  • Приложение должно работать в Windows и Linux. Так что частичная кросс-платформенность является проблемой.
  • Я собираюсь использовать некоторые библиотеки, такие как TBB, Boost, Qt, которые могут иметь свои собственные библиотеки, такие как tbb.dll и т. Д.

Каковы плюсы и минусы статического или динамического связывания Lib_A с Exe и Lib_Bx? Как повлиять на производительность, размер системы и т. Д.? Есть ли опасные или сложные ситуации, которые я мог бы допустить, кроме того, для каждой ОС мне нужно использовать один и тот же компилятор для Exe, Lib_A и Lib_Bx.

Дизайн всей системы является для меня очень сложной проблемой, поэтому любые комментарии будут оценены.

Большое спасибо.

Ответы [ 4 ]

6 голосов
/ 17 января 2011

Из того, что я понимаю в описании вашего проекта, вы должны динамически связывать Lib_A: если вы статически связываете Lib_A с каждой из ваших общих библиотек Lib_Bx, вы дублируете x раз код Lib_A и статические переменные.

Скажите, если у вас есть класс в Lib_A, который имеет вид:

class BaseKlass
{
  static int instance_count;
  ...
};

instance_count будет продублирован во всех ваших общих библиотеках, что сделает невозможным для BaseKlass подсчет его экземпляров.

Возможно, вас укусили более тонкие проблемы с виртуальными таблицами или RTTI (dynamic_cast) и т. Д.

Вам следует взглянуть на этот boost.python документ , в котором описываетсяпроблемы, связанные с тем, что я упомянул.

Boost.python позволяет создавать модули Python (динамические библиотеки), которые должны загружаться в одном и том же процессе.Каждый модуль python, созданный с помощью boost.python, если они должны взаимодействовать друг с другом на уровне c ++, например, выводить класс B в модуле из класса A в другом модуле, должен динамически связываться с библиотекой boost.python, чтобы избежать проблем.

3 голосов
/ 17 января 2011

Большим преимуществом статической компоновки является то, что вам не нужно отправлять кучу DLL.Если вы не планируете поставлять голый исполняемый файл, я думаю, что это не проблема.

Динамическое связывание имеет некоторые большие преимущества.Вам не нужно перекомпилировать все приложение каждый раз, когда вы вносите изменения, только измененные библиотеки DLL.Вы можете распространять обновленные DLL отдельно от остальной части приложения, если они совместимы с ABI.

Может быть проще использовать один и тот же компилятор в Windows и Linux, но вам определенно не обязательно использовать один и тот же компилятор.

Пока вы придерживаетесь переносимых библиотек, самая большая разницамежду Windows и Linux обычно есть система сборки.Некоторые разработчики поддерживают совершенно отдельные системы сборки, но существует множество кроссплатформенных систем сборки, таких как cmake.

2 голосов
/ 17 января 2011

Вы хотите создавать новые классы времени выполнения?C ++ не предназначен для такой работы.Классы C ++ являются статическими и должны существовать во время компиляции.Общие динамически загружаемые библиотеки не предназначены для решения этой проблемы.

Самое простое решение - встроить интерпретатор языка, который имеет динамические типы (например, Lua), и записать в него динамические объекты времени выполнения.

Если вы действительно хотите взаимодействоватьскомпилированные во время выполнения модули независимы от платформы, тогда вам лучше использовать не зависящий от языка и платформы интерфейс, такой как CORBA.Тогда все вещи, скомпилированные и запущенные на вашем компьютере с Linux и Windows, могут взаимодействовать друг с другом и собирать новых участников, чтобы присоединиться к банде.

0 голосов
/ 28 января 2011

В принципе это все возможно, если все три являются DLL - вы можете запустить компилятор из своего приложения и затем динамически загрузить новую DLL. Это действительно так же, как любая другая архитектура плагинов (рассмотрим библиотеки Lib_Bx как плагины).

Я бы спросил, является ли это мудрым подходом. Вам нужна полная гибкость компилятора C ++ для вашего решения? Вы профилировали различные способы решения проблемы? Если вы выполняете числовую обработку, будет ли что-то вроде OpenCL лучшим подходом?

...