Plattformübergreifende Weiterleitung der Standardeingabe und -ausgabe des erzeugten Prozesses in nativem C / C ++ (Bearbeitung mit Lösung)

8

Ich habe einen String-Befehl, den ich asynchron ausführen möchte, während ich auf seine Eingabe schreibe und seine Ausgabe lese. 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ß.

popen - schön und einfach, gibt FILE * zurück, das überall einfach zu konsumieren ist. Aber hier ist, was MSDN über _popen sagen muss:

  

Wenn in einem Windows-Programm verwendet, wird die   Die Funktion _popen gibt einen ungültigen Dateizeiger zurück, der das Programm verursacht   auf unbegrenzte Zeit zu reagieren.   _popen funktioniert in einer Konsolenanwendung ordnungsgemäß. Um ein Windows zu erstellen   Anwendung, die Eingabe umleitet und   Ausgabe, siehe Erstellen eines untergeordneten Prozesses   mit umgeleitetem Eingang und Ausgang in   das Platform SDK.

und so popen kommt nicht in Frage (edit: weil ich möchte, dass mein Code in der 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 in FILE* oder int fd umzuwandeln oder umgekehrt? (Google hat mich hier noch einmal gescheitert, alle Keywords, die ich ausprobiert habe, sind viel zu oft benutzt worden)

Gibt es einen besseren Weg, die ganze Sache mit wenig plattformspezifischem Code zu machen?

Externe Bibliotheken kommen nicht in Frage, aber die Pflege von Abhängigkeiten ist ein Problem, besonders auf mehreren Plattformen, daher möchte ich die Abhängigkeiten reduzieren. Ich habe auch keine solche Bibliothek im Boost gefunden.

Nur für das Protokoll, was am Ende für mich funktionierte. Unter Windows / MSVC, CreatePipe() + CreateProcess() wie beschrieben hier , mit _open_osfhandle() gefolgt von _fdopen() , um FILE* für die Prozesseingabe und -ausgabe zu erhalten. Auf Linux / GCC, nichts neues hier, creating pipe() s; fork() then dup2() die Pfeifen; %Code%; exec() für die relevanten Dateideskriptoren. Auf diese Weise ist nur der Prozess-Laichcode plattformabhängig (was in Ordnung ist, da ich unter Windows gerne zusätzliche fdopen() -Parameter steuern möchte), das Schreiben von Eingaben und das Lesen von Ausgaben erfolgt über den Standard STARTUPINFO und verwandte Funktionen.

    
sbk 09.01.2010, 15:43
quelle

2 Antworten

2

zum Konvertieren von Fenstern HANDLE s in C-Dateideskriptoren verwenden Sie _open_osfhandle Ссылка

EDIT: Dieses Beispiel hat mir auch bei einem ähnlichen Problem geholfen: Ссылка

    
smerlin 09.01.2010, 17:20
quelle
6

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

Ich habe es unter Linux, Darwin und Windows benutzt 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 glaube nicht, dass es einen Weg gibt, eine Bibliothek zu benutzen (außer das Schreiben eigener Variationen für jede Plattform).

    
Adam Bowen 09.01.2010 15:47
quelle