2010-01-09 10 views
8

Ich habe einen String-Befehl, den ich asynchron ausführen möchte, während ich auf seine Eingabe schreiben und seine Ausgabe lesen. Klingt einfach, richtig, der Teufel ist in der Cross-Plattform. Ich ziele sowohl auf MSVC/Win32 als auch auf gcc/Linux ab und möchte natürlich die minimale Menge an plattformspezifischem Code schreiben. Mein Google-Fu hat mich im Stich gelassen, ich bekomme zu viel Lärm für meine Fragen, also begann ich mit dem, was ich weiß.Cross-Plattform-Umleitung von Standard-Eingabe und Ausgabe von erzeugten Prozess in nativem C/C++ (bearbeiten mit Lösung)

popen - nett und einfach, gibt FILE * zurück, das überall einfach zu konsumieren ist. Aber hier ist, was MSDN have to say about _popen:

Wenn in einem Windows-Programm verwendet, die _popen Funktion gibt einen ungültigen Dateizeiger, der das Programm verursacht auf unbestimmte Zeit zu reagieren. _popen funktioniert ordnungsgemäß in einer Konsolenanwendung. Informationen zum Erstellen einer Windows-Anwendung , die die Eingabe und die Ausgabe umleitet, finden Sie unter Erstellen eines untergeordneten Prozesses mit umgeleiteter Eingabe und Ausgabe in dem Platform SDK.

und so Popen ist nicht in Frage (bearbeiten: weil ich möchte, dass mein Code in GUI-Anwendung funktioniert). Die Windows-Art, es zu tun, ist meiner Meinung nach ziemlich hässlich und ausführlich. Ich könnte mit plattformspezifischem Spawn-Code leben, aber ich möchte, dass der I/O-Code derselbe ist. Hier traf ich jedoch eine Wand zwischen dem WinAPI HANDLE s und C FILE* und int Dateideskriptor. Gibt es eine Möglichkeit, ein HANDLE zu FILE* oder int fd "umzuwandeln" oder umgekehrt? (Google scheiterte mich noch einmal an diesem, alle Keywords, die ich ausprobiert habe, sind viel zu oft benutzt)

Gibt es bessere Möglichkeit, das ganze mit wenig plattformspezifischen Code zu machen?

Externe Bibliotheken sind nicht ausgeschlossen, aber Abhängigkeitspflege ist ein Schmerz, besonders auf mehreren Plattformen, also möchte ich Abhängigkeiten reduzieren. Ich habe auch keine solche Bibliothek im Boost gefunden.


Nur für das Protokoll, was für mich am Ende funktionierte. Unter Windows/MSVC, CreatePipe() + CreateProcess() wie beschrieben here, mit _open_osfhandle() gefolgt von _fdopen(), um FILE* zum Prozesseingang und -ausgang zu erhalten. Auf Linux/GCC, nichts Neues hier, Erstellen pipe() s; fork() dann dup2() die Rohre; exec(); fdopen() über die relevanten Dateideskriptoren. Auf diese Weise ist nur der Prozess-Laichcode plattformabhängig (was in Ordnung ist, da unter Windows ich zusätzliche STARTUPINFO Parameter steuern möchte), das Schreiben der Eingabe und das Lesen der Ausgabe erfolgt über den Standard FILE* und zugehörige Funktionen.

+0

Was Sie nicht sagen, wenn Sie eine GUI schreiben oder eine Konsolen-App Wenn letzteres funktioniert, funktioniert popen() unter Windows. –

Antwort

6

Gib libexecstream einen Wirbel. Es ist plattformübergreifend und ermöglicht es Ihnen, die Eingabe-, Ausgabe- und Fehlerströme eines Prozesses asynchron als C++ - Stil-Streams abzufangen.

Ich habe es auf Linux, Darwin und Windows verwendet und es scheint zu funktionieren. Es ist auch ziemlich leicht, integriert sich also in Projekte mit wenig Schmerzen und hat eine ziemlich offene BSD-Lizenz. Ich denke nicht, dass es einen Weg gibt, eine Bibliothek zu benutzen (außer dass Sie für jede Plattform eigene Variationen schreiben).