Подтвердить что ты не робот

Написание кросс-платформенного кода на С++ (Windows, Linux и Mac OSX)

Это моя первая попытка записать что-либо даже немного сложное в С++, я пытаюсь создать общую библиотеку, с которой я могу взаимодействовать с 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 - но я также очень ценю любую информацию или ресурсы, которые люди могли бы предложить, как лучше писать такой код....

4b9b3361

Ответ 1

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

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 или удара #error.

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


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


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

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

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

Ответ 2

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

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

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

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

Ответ 3

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

Таким образом, ваш код был следующим:

bool probe(){
}

Вот почему компилятор жалуется на достижение конца не-void функции. Нет предложения return.


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

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

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

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

Удачи;)

Ответ 4

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

Ответ 5

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