36 votes

Rédaction de code C++ multiplateforme (Windows, Linux et Mac OSX)

C'est ma première tentative d'écrire quelque chose d'un peu compliqué en C++, j'essaie de construire une bibliothèque partagée avec laquelle je peux m'interfacer à partir d'Objective-C et d'applications .NET (ok, cette partie viendra plus tard...).

Le code que j'ai est -

#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;
}

J'ai un avertissement du compilateur, simplement untitled: In function ‘bool probe()’:untitled:29: warning: control reaches end of non-void function - mais j'apprécierais également toute information ou ressource que les gens pourraient suggérer pour mieux écrire ce genre de code.....

46voto

stijn Points 13405

Au lieu de vous répéter et d'écrire les mêmes lignes #ifdef .... encore, encore et encore, vous êtes peut-être mieux de déclarer la méthode probe() dans un en-tête, et de fournir trois fichiers sources différents, un pour chaque plateforme. Ceci a également l'avantage que si vous ajoutez une plateforme, vous n'avez pas à modifier toutes vos sources existantes, mais simplement à ajouter de nouveaux fichiers. Utilisez votre système de construction pour sélectionner le fichier source approprié.

Exemple de structure :

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

L'avertissement est dû au fait que probe() ne renvoie pas de valeur. En d'autres termes, aucune des trois #ifdefs ne correspond.

33voto

Je vais aborder cette fonction spécifique :

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
}

En l'écrivant de cette façon, comme une chaîne de if-elif-else, on élimine l'erreur parce qu'il est impossible de compiler sans une déclaration de retour valide ou sans toucher à l'erreur #.

(Je crois que WIN32 est défini à la fois pour les Windows 32 et 64 bits, mais je ne pourrais pas vous le dire définitivement sans le vérifier. Cela simplifierait le code).


Malheureusement, vous ne pouvez pas utiliser #ifdef _WIN32 || _WIN64 : voir http://codepad.org/3PArXCxo pour un exemple de message d'erreur. Vous pouvez utiliser l'option spéciale "preprocessing-only". défini opérateur, comme je l'ai fait ci-dessus.


En ce qui concerne le fractionnement des plates-formes en fonction des fonctions ou des fichiers entiers (comme les Proposition de ), vous pouvez ou non vouloir le faire. Cela dépendra des détails de votre code, tels que la quantité de code partagée entre les plateformes et ce que vous (ou votre équipe) trouvez le mieux pour maintenir la synchronisation des fonctionnalités, entre autres.

De plus, vous devriez gérer la sélection de la plateforme dans votre système de construction, mais cela ne signifie pas que vous ne pouvez pas utiliser le préprocesseur : utilisez des macros définies de manière conditionnelle (par le makefile ou le système de construction) pour chaque plateforme. En fait, c'est souvent la solution la plus pratique avec les modèles et les fonctions en ligne, ce qui la rend plus flexible que d'essayer d'éliminer le préprocesseur. Elle se combine bien avec l'approche du fichier entier, donc vous pouvez toujours l'utiliser lorsque c'est approprié.

Vous pourriez vouloir avoir un seul en-tête de configuration qui traduise toutes les diverses macros spécifiques au compilateur et à la plate-forme en macros bien connues et comprises que vous contrôlez. Vous pouvez également ajouter -DBEAKS_PLAT_LINUX à la ligne de commande de votre compilateur - via votre système de compilation - pour définir cette macro (n'oubliez pas d'utiliser un préfixe pour les noms de macro).

5voto

ereOn Points 18624

Il semble qu'aucun des TARGET_OS_MAC , __linux__ , _WIN32 o _WIN64 est défini au moment où vous compilez votre code.

Donc c'est comme si ton code était :

bool probe(){
}

C'est pourquoi le compilateur se plaint d'atteindre la fin d'une fonction non vide. Il n'y a pas de return clause.


Par ailleurs, pour la question plus générale, voici mes directives pour le développement de logiciels/librairies multi-plateformes/architectures :

Évitez les cas particuliers. Essayez d'écrire du code qui est indépendant du système d'exploitation.

Lorsque vous traitez des éléments spécifiques au système, essayez d'envelopper les choses dans des classes "opaques". Par exemple, si vous avez affaire à des fichiers (API différentes sous Linux et Windows), essayez de créer une classe de type File qui intègre toute la logique et fournit une interface commune, quel que soit le système d'exploitation. Si une fonctionnalité n'est pas disponible sur l'un des systèmes d'exploitation, il faut faire avec : si la fonctionnalité n'a pas de sens pour un système d'exploitation spécifique, il est souvent préférable de ne rien faire du tout.

En bref : moins #ifdef le mieux. Et quelle que soit la portabilité de votre code, testez-le sur toutes les plateformes avant de le diffuser.

Bonne chance ;)

1voto

Tristan Points 1542

L'avertissement est dû au fait que si aucune des définitions n'est effectivement définie, alors vous n'avez pas de return dans votre fonction de sonde. La solution est d'ajouter une fonction par défaut return .

1voto

Lee Hambley Points 3160

Pour ajouter quelque chose à cela, outre les options remarquables ci-dessus, les directives __linux__ y _WIN32 sont connus du compilateur, où les TARGET_OS_MAC ne l'était pas, cela peut être résolu en utilisant la directive __APPLE__ . Source : http://www.winehq.org/pipermail/wine-patches/2003-July/006906.html

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X