Fortran-Ausgaben auf stdout abfangen
-
Hai
Ich bin mir nicht sicher ob das hier richtig ist, aber ich suche einen portablen weg, die Konsolenausgabe einer hinzugelinkten Fortran lib, die per write(,) erfolgt, in C++ abzufangen und in einen string umzuleiten. Ich nehme hier nur an dass es sich um das selbe stdout handelt, aber ich weiß das nicht.
Daher die Frage, gibt es eine Möglichkeit das zu bewerkstelligen? Der Grund für diesen Kniff ist dass der Fortran code unverändert bleiben soll.
-
Hmmm...das wäre mit einer Helferapplikation einfacher (Stichwort popen bzw. _popen). Um ein paar ifdefs wirst du vermutlich nicht herumkommen, und etwas hackig wird die Angelegenheit wohl auch werden.
Was mir spontan einfällt, ist, eine named pipe, ein UNIX-Socket oder etwas vergleichbares aufzumachen, stdout mit freopen dahin umzuleiten und am anderen Ende der Pipe die Ausgaben in Strings zu lesen.
Vorstellbar wäre auch, stdout nach /dev/null bzw. NUL umzuleiten und mit setvbuf einen (großen) Buffer, der unter deiner Kontrolle steht, als Blockpuffer (_IOFBF) zwischenzuschalten. Solange dieser größer ist als die Ausgabe der Bibliothek, solltest du dann die Funktion aufrufen, ihre Ausgabe aus dem Buffer lesen und mit fflush weiter nach /dev/null schicken können. Wie zuverlässig dieser Ansatz in der Praxis ist, kann ich allerdings nicht sagen; für diesen Zweck ist setvbuf eigentlich nicht gedacht.
-
vielen Dank, ich probier die variante mit _popen mal, sieht am einfachsten aus.
-
Wo ich grad drüber nachdenke, könnte man den Kindprozess auch von Hand bauen und abhören; dann ginge das auch in einer Bibliothek. In C mit POSIX sähe das etwa so aus:
#include <unistd.h> #include <stdio.h> void write_hello(void) { /* Hier könnte auch der FORTRAN-Code aufgerufen werden. */ puts("Nein, ich bin dein Sohn!"); } int main(void) { pid_t pid; int pipes[2]; pipe(pipes); pid = fork(); if(pid == 0) { /* Kindprozess */ close(pipes[0]); dup2(pipes[1], STDOUT_FILENO); close(pipes[1]); write_hello(); } else { /* Vaterprozess */ char buffer[1024]; ssize_t bytes_read; close(pipes[1]); bytes_read = read(pipes[0], buffer, 1023); buffer[bytes_read] = '\0'; printf("Vaderprozess hört: %s", buffer); wait(NULL); close(pipes[0]); } return 0; }Unter Windows hast du kein POSIX, aber viele POSIX-Funktionen gibt es dort in leicht abgewandelter Form - wie etwa _popen statt popen. Mit etwas Glück lässt sich das mit endlichem Arbeitsaufwand kapseln; befrag die MSDN am besten nach _pipe, _fork, _close, _dup, _read und _wait.