Написание кроссплатформенного кода C ++ (Windows, Linux и Mac OSX) - PullRequest
35 голосов
/ 02 сентября 2010

Это моя первая попытка написать что-нибудь, даже немного сложное на C ++, я пытаюсь создать общую библиотеку, с которой я могу взаимодействовать, из Objective-C и приложений .NET (хорошо, эта часть будет позже ...)

Код, который у меня есть, -

#ifdef TARGET_OS_MAC
  // Mac Includes Here
#endif

#ifdef __linux__
  // Linux Includes Here
  #error Can't be compiled on Linux yet
#endif

#ifdef _WIN32 || _WIN64
  // Windows Includes Here
  #error Can't be compiled on Windows yet
#endif

#include <iostream>

using namespace std;

bool probe(){
  #ifdef TARGET_OS_MAC
    return probe_macosx();
  #endif
  #ifdef __linux__
    return probe_linux();
  #endif
  #ifdef _WIN32 || _WIN64
    return probe_win();
  #endif
}

bool probe_win(){
  // Windows Probe Code Here
  return true;
}

int main(){

  return 1;
}

У меня есть предупреждение компилятора, просто untitled: In function ‘bool probe()’:untitled:29: warning: control reaches end of non-void function - но я также буду очень признателен за любую информацию или ресурсы, которые люди могут предложить, каклучше написать такой код ....

Ответы [ 5 ]

46 голосов
/ 02 сентября 2010

вместо того, чтобы повторяться и писать те же строки #ifdef .... снова, снова и снова, возможно, вам лучше объявить метод probe () в заголовке и предоставить три разных исходных файла, один длякаждая платформа.Это также имеет то преимущество, что если вы добавляете платформу, вам не нужно изменять все существующие источники, а просто добавлять новые файлы.Используйте свою систему сборки, чтобы выбрать соответствующий исходный файл.

Пример структуры:

include/probe.h
src/arch/win32/probe.cpp
src/arch/linux/probe.cpp
src/arch/mac/probe.cpp

Предупреждение, потому что probe () не возвращает значение.Другими словами, ни одно из трех #ifdefs не соответствует.

32 голосов
/ 02 сентября 2010

Я рассмотрю эту конкретную функцию:

bool probe() {
#ifdef TARGET_OS_MAC
  return probe_macosx();
#elif defined __linux__
  return probe_linux();
#elif defined _WIN32 || defined _WIN64
  return probe_win();
#else
#error "unknown platform"
#endif
}

Запись в таком виде, как цепочка if-elif-else, устраняет ошибку, потому что невозможно скомпилировать без действительного оператора return илиНажав на ошибку #.

(Я думаю, что WIN32 определен как для 32-, так и для 64-битной Windows, но я не могу сказать вам однозначно, не посмотрев его. Это упростит код.)


К сожалению, вы не можете использовать #ifdef _WIN32 ||_WIN64: см. http://codepad.org/3PArXCxo для примера сообщения об ошибке.Вы можете использовать специальный только для предварительной обработки определенный оператор, как я делал выше.


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

Кроме того, вы должны обращаться с платформойвыбор в вашей системе сборки, но это не значит, что вы не можете использовать препроцессор: используйте макросы, условно определенные (make-файлом или системой сборки) для каждой платформы.Фактически, это часто наиболее практичное решение с шаблонами и встроенными функциями, что делает его более гибким, чем попытка исключить препроцессор.Он хорошо сочетается с подходом на основе целых файлов, поэтому вы все равно используете его там, где это необходимо.

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

5 голосов
/ 02 сентября 2010

Кажется, что ни один из TARGET_OS_MAC, __linux__, _WIN32 или _WIN64 не определен во время компиляции вашего кода.

Итак, ваш код был таким:

bool probe(){
}

Вот почему компилятор жалуется на то, что достигнут конец функции, не являющейся void. Нет return предложения.


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

Избегайте особых случаев. Попробуйте написать код, независимый от ОС.

Когда имеешь дело с системными вещами, попытайся обернуть вещи в "непрозрачные" классы. Например, если вы имеете дело с файлами (разные API в Linux и Windows), попробуйте создать класс File, который будет встраивать всю логику и обеспечивать общий интерфейс, независимо от операционной системы. Если какая-либо функция недоступна в одной из ОС, с этим следует справиться: если эта функция не имеет смысла для конкретной ОС, часто вполне нормально вообще ничего не делать.

Короче говоря: чем меньше #ifdef, тем лучше. И независимо от того, насколько переносим ваш код, протестируйте его на каждой платформе перед его выпуском.

Удачи;)

1 голос
/ 08 сентября 2010

Чтобы добавить к этому что-то еще, кроме указанных выше параметров, директивы __linux__ и _WIN32 известны компилятору, где директивы TARGET_OS_MAC не было, это можно решить с помощью __APPLE__ , Источник: http://www.winehq.org/pipermail/wine-patches/2003-July/006906.html

1 голос
/ 02 сентября 2010

Предупреждение состоит в том, что если на самом деле не определено ни одно из определений, то в вашей функции пробника нет return. Исправление для этого по умолчанию return.

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