2010-01-09 3 views
8

J'ai une commande de chaîne que je voudrais exécuter de manière asynchrone en écrivant à son entrée et en lisant sa sortie. Cela semble facile, à droite, le diable est dans la multiplateforme. Je cible à la fois MSVC/Win32 et gcc/Linux et je veux évidemment écrire le minimum de code spécifique à la plate-forme. Mon google-fu m'a échoué, j'ai trop de bruit pour mes questions, alors j'ai commencé avec ce que je sais.Rediffusion multiplateforme de l'entrée et de la sortie standard du processus engendré en C/C++ natif (édition avec solution)

popen - agréable et facile, renvoie FICHIER * qui est facile à consommer partout. Mais voici ce que MSDN have to say about _popen:

Si elle est utilisée dans un programme Windows, la fonction retourne _popen un pointeur de fichier non valide qui provoque le programme cesser de répondre indéfiniment. _popen fonctionne correctement dans une application console. Pour créer une application Windows qui redirige l'entrée et la sortie , voir Création d'un processus enfant avec entrée et sortie redirigées dans le kit de développement Platform SDK.

et ainsi popen est hors de question (edit: parce que je voudrais mon code pour l'application dans l'interface graphique). La façon Windows de le faire est à mon avis plutôt laide et verbeuse. Je pourrais vivre avec du code spawn spécifique à la plateforme mais je voudrais au moins que le code d'E/S soit le même. Ici, cependant, je frappe un mur entre le WinAPI HANDLE s et C FILE*, et int descripteur de fichier. Y a-t-il un moyen de "convertir" un HANDLE en FILE* ou int fd ou vice versa? (Google m'a échoué une fois de plus sur celui-ci, tous les mots-clés que j'ai essayé sont trop utilisés)

Y at-il une meilleure façon de faire le tout avec peu de code spécifique à la plate-forme?

Les bibliothèques externes ne sont pas hors de question, cependant la maintenance des dépendances est un problème, en particulier sur plusieurs plates-formes, donc je voudrais réduire les dépendances. Je n'ai pas trouvé une telle bibliothèque en boost aussi. Juste pour l'enregistrement, ce qui a fonctionné pour moi à la fin. Sur Windows/MSVC, CreatePipe() + CreateProcess() comme indiqué here, en utilisant _open_osfhandle() suivi par _fdopen() pour obtenir FILE* à l'entrée et la sortie de processus. Sur Linux/GCC, rien de nouveau ici, créant pipe() s; fork() puis dup2() les tuyaux; exec(); fdopen() sur les descripteurs de fichiers pertinents. De cette façon, seul le code de génération de processus est dépendant de la plateforme (ce qui est normal, comme sur Windows, je voudrais contrôler des paramètres supplémentaires), l'écriture d'entrée et la sortie de lecture s'effectuent via les fonctions standard FILE*.

+0

Vous ne dites pas si vous écrivez une interface graphique ou une application de console. Si ce dernier, popen() fonctionne sur Windows. –

Répondre

6

Donner libexecstream un tourbillon. Il est multi-plateforme et vous permet de piéger les flux d'entrée, de sortie et d'erreur d'un processus de manière asynchrone en tant que flux de style C++. Je l'ai utilisé sous Linux, Darwin et Windows et ça semble fonctionner. Je l'ai utilisé sous Linux, Darwin et Windows. Il est également assez léger, s'intègre donc dans les projets sans trop de peine et possède une licence BSD assez ouverte. Je ne pense pas qu'il existe un moyen d'utiliser une bibliothèque (autre que d'écrire vos propres variations pour chaque plate-forme).

Questions connexes