Как мне написать программу на C ++, которая будет легко компилироваться в Linux и Windows? - PullRequest
16 голосов
/ 26 января 2009

Я делаю программу на C ++.

Одна из моих самых больших неприятностей с C ++ - это предполагаемая независимость от платформы.

Вы все, наверное, знаете, что практически невозможно скомпилировать программу Linux C ++ для Windows и Windows для Linux без потока загадочных ошибок и специальных файлов для платформы.

Конечно, вы всегда можете переключиться на какую-то эмуляцию, такую ​​как Cygwin и wine, но я спрашиваю вас, разве нет другого пути?

Ответы [ 9 ]

37 голосов
/ 26 января 2009

Сам язык кроссплатформенный, но большинство библиотек - нет, но следует помнить о трех вещах, если вы хотите полностью кросс-платформенные при программировании на C ++.

Во-первых, вам нужно начать использовать какую-то кроссплатформенную систему сборки, например, SCons . Во-вторых, вам нужно убедиться, что все библиотеки, которые вы используете, созданы для кроссплатформенности. И небольшой третий момент: я бы порекомендовал использовать компилятор, который существует на всех ваших целевых платформах: gcc здесь имеет в виду (C ++ довольно сложный зверь, и у всех компиляторов есть свои специфические особенности).

У меня есть еще несколько предложений относительно графических пользовательских интерфейсов для вас. Есть несколько из них доступных для использования, три наиболее заметные из них:

GTK + и QT - это два API, которые поставляются со своими собственными наборами виджетов (кнопками, списками и т. Д.), Тогда как wxWidgets является скорее оболочкой API для работающих на данный момент платформ. Это означает, что два первых могут выглядеть немного по-другому по сравнению с остальной системой, в то время как последний будет выглядеть как нативная программа.

И если вы занимаетесь программированием игр, вы можете выбирать из множества одинаковых API, все они также кроссплатформенные. Два наиболее полнофункциональных из известных мне:

Оба содержат все, от графики до ввода и аудио-подпрограмм, либо через плагины или встроенные.

Кроме того, если вам кажется, что стандартной библиотеки в C ++ немного не хватает, посмотрите Boost , чтобы узнать о кроссплатформенности общего назначения.

Удачи.

13 голосов
/ 26 января 2009

C ++ является кроссплатформенным. Кажется, проблема в том, что вы используете зависимые от платформы библиотеки.

Полагаю, вы действительно говорите о компонентах пользовательского интерфейса - в этом случае я предлагаю использовать что-то вроде GTK +, Qt или wxWindows - каждый из которых имеет компоненты пользовательского интерфейса, которые можно скомпилировать для разных систем.

Единственное решение для вас - найти и использовать независимые от платформы библиотеки.

И, кроме того, ни cygwin, ни Wine не являются эмуляциями - они на 100% являются собственными реализациями с той же функциональностью, что и соответствующие им системы.

9 голосов
/ 26 января 2009

Как только вы узнаете о проблемах, на самом деле это не так сложно. Весь код, над которым я сейчас работаю, компилируется на 32- и 64-битной Windows, все версии Linux , а также Unix (Sun, HP и IBM). Очевидно, что это не продукты GUI. Кроме того, мы не используем сторонние библиотеки, если сами не собираем их.

У меня есть один файл .h, который содержит весь специфичный для компилятора код. Например, Microsoft и gcc не согласны с тем, как указать 8-разрядное целое число. Так что в .h, у меня есть

#if defined(_MSC_VER)
   typedef __int8 int8_t;
 #elif defined(__unix)
   typedef char int8_t;
 #endif

Существует также довольно много кода, который унифицирует определенные вызовы функций более низкого уровня, например:

#if defined(_MSC_VER)
  #define SplitPath(Path__,Drive__,Name__,Ext__) _splitpath(Path__,Drive__,Dir__,Name__,Ext__)
#elif defined(__unix)
  #define SplitPath(Path__,Drive__,Name__,Ext__) UnixSplitPath(Path__,Drive__,Name__,Ext__)
#endif

Теперь, в этом случае, я считаю, что мне нужно было написать функцию UnixSplitPath () - будут времена, когда вам нужно. Но в большинстве случаев вам просто нужно найти правильную функцию замены. В моем коде я буду вызывать SplitPath (), даже если это не встроенная функция ни на одной платформе; #defines разберутся для меня. Тренироваться нужно некоторое время.

Верьте или нет, мой .h файл имеет длину всего 240 строк. Там действительно не так много. И это включает в себя обработку проблем с порядком байтов.

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

Другой секрет, который я могу вам дать: часто создавайте свой проект на всех платформах (особенно в начале). Это намного проще, когда вы устраняете проблемы компилятора в зародыше. Не ждите, пока закончите разработку, прежде чем пытаться перейти на кроссплатформенность.

2 голосов
/ 26 января 2009

Придерживайтесь ANSI C ++ и библиотек, которые являются кроссплатформенными, и у вас все будет хорошо.

1 голос
/ 26 января 2009

Создайте некоторый низкоуровневый слой, который будет содержать весь специфичный для платформы код в вашем проекте. Реализуйте 2 версии этого уровня - одну для Windows и одну для Linux - с тем же интерфейсом и соберите их для 2 библиотек. Получите доступ ко всем функциональным возможностям платформы в вашем проекте через этот интерфейс.

Этот слой может содержать общие классы для доступа к файлам, печати, графического интерфейса и т. Д.

Весь (теперь не зависящий от платформы) код, который использует этот слой, теперь можно скомпилировать один раз в Windows и один раз в Linux.

0 голосов
/ 26 января 2009

Также Linux и Windows имеют разные модели данных. Смотрите статью: Забытые проблемы разработки 64-битных программ

0 голосов
/ 26 января 2009

Стандарт C ++ - код компилируется без ошибок на любой платформе. Попробуйте использовать Bloodshed Dev C ++ на Windows (вместо VC ++ / Borland C ++).

Как Bloodshed Dev C ++ подтверждает стандарты C ++, так и программы, скомпилированные с его использованием, будут скомпилированы на Linux без ошибок в большинстве случаев.

0 голосов
/ 26 января 2009

Предложения:

  • Используйте typedef для целых. Или #include . Некоторые машины думают, что int составляет 8 байтов, некоторые 4. (Раньше было 2 и 4. Как изменилось время.)

  • Используйте инкапсуляцию везде, где это возможно. Компилятор моего последнего окна подумал, что% lld был% I64d ", дал неправильные возвращаемые значения для vsnprintf (), похожие проблемы с close () и сокетами и т. Д.

  • Остерегайтесь ограничений размера стека / размера буфера. Я столкнулся с ограничением буфера UDP 8k под Windows, среди других проблем.

  • По какой-то причине мой компилятор C ++ для Windows не принимает выделения динамического размера из стека. Например: void foo (int a) {int b [a]; } Будьте в курсе таких вещей. Спланируйте, как вы будете перекодировать.

  • # ifdef может быть вашим лучшим другом. И твой злейший враг! (Одновременно!)

Это, безусловно, можно сделать. Но собирайте и тестируйте рано и часто!

0 голосов
/ 26 января 2009

Скомпилируйте его в Window и снова в Linux. Если вы не использовали библиотеки для конкретной платформы, это должно работать. Это не похоже на Java, где вы компилируете его один раз, и он работает везде. Никто не создал виртуальную машину для C ++, и, вероятно, никогда не будет. Код, который вы пишете на C ++, будет работать на любой платформе. Вам просто нужно сначала скомпилировать его на каждой платформе.

...