Wie man (vorübergehend) stdout erfasst
Wie kann ich stdout in Nim vorübergehend erfassen?
Ich hätte gerne eine Vorlage mit folgender Signatur:
template captureStdout(ident: untyped, body: untyped) = discard
So dass dieser Code ( main.nim) fehlerfrei ausgeführt wird:
var msg = "hello"
echo msg & "1"
var s: string
captureStdout(s):
echo msg & "2"
msg = "ciao"
echo msg & "3"
assert s == "hello2\n"
und die Ausgabe sollte sein:
hello1
ciao3
aktuelle Bemühungen
Derzeit kann ich stdout mit einer temporären Datei erfassen, aber ich kann es nicht wieder an stdout freigeben. Ich mache das mit folgendem:
template captureStdout*(ident: untyped, body: untyped) =
discard reopen(stdout, tmpFile, fmWrite)
body
ident = readFile(tmpFile)
Dies main.nimläuft ohne Assertionsfehler, aber die Ausgabe erfolgt nur
hello1
und in tmpFile sehe ich:
hello2
ciao3
Antworten
Wenn Sie aufrufen reopen, weisen Sie die Variable stdouteiner Variablen zu File, in die geschrieben wird tmpFile.
Um die Ausgabe an das System STDOUT zu drucken, müssen Sie die Variable stdouteiner Variablen zuweisen, die in Ihr System STDOUT Fileschreibt.
Daher unterscheiden sich die Antworten zwischen Linux und Windows.
Unter Linux besteht die Möglichkeit darin, den Dateideskriptor mit den Funktionen dup und dup2 C zu duplizieren stdoutund eine andere Datei zu verwenden (damit Sie stdout wiederherstellen können). Da dup und dup2 nicht in system/ioNim enthalten sind, benötigen wir Bindungen zu unistd.h.
Hier ist ein Beispiel:
#Create dup handles
proc dup(oldfd: FileHandle): FileHandle {.importc, header: "unistd.h".}
proc dup2(oldfd: FileHandle, newfd: FileHandle): cint {.importc,
header: "unistd.h".}
# Dummy filename
let tmpFileName = "tmpFile.txt"
template captureStdout*(ident: untyped, body: untyped) =
var stdout_fileno = stdout.getFileHandle()
# Duplicate stoud_fileno
var stdout_dupfd = dup(stdout_fileno)
echo stdout_dupfd
# Create a new file
# You can use append strategy if you'd like
var tmp_file: File = open(tmpFileName, fmWrite)
# Get the FileHandle (the file descriptor) of your file
var tmp_file_fd: FileHandle = tmp_file.getFileHandle()
# dup2 tmp_file_fd to stdout_fileno -> writing to stdout_fileno now writes to tmp_file
discard dup2(tmp_file_fd, stdout_fileno)
#
body
# Force flush
tmp_file.flushFile()
# Close tmp
tmp_file.close()
# Read tmp
ident = readFile(tmpFileName)
# Restore stdout
discard dup2(stdout_dupfd, stdout_fileno)
proc main() =
var msg = "hello"
echo msg & "1"
var s: string
captureStdout(s):
echo msg & "2"
msg = "ciao"
echo msg & "3"
echo ">> ", s
assert s == "hello2\n"
when isMainModule:
main()
# Check it works twice
main()