stdout을 (일시적으로) 캡처하는 방법
Sep 23 2020
Nim에서 stdout을 임시로 캡처하려면 어떻게합니까?
다음 서명이있는 템플릿을 갖고 싶습니다.
template captureStdout(ident: untyped, body: untyped) = discard
이 코드 ( main.nim)는 오류없이 실행됩니다.
var msg = "hello"
echo msg & "1"
var s: string
captureStdout(s):
echo msg & "2"
msg = "ciao"
echo msg & "3"
assert s == "hello2\n"
출력은 다음과 같아야합니다.
hello1
ciao3
현재의 노력
현재 임시 파일을 사용하여 stdout을 캡처 할 수 있지만 stdout으로 다시 릴리스 할 수 없습니다. 다음과 같이합니다.
template captureStdout*(ident: untyped, body: untyped) =
discard reopen(stdout, tmpFile, fmWrite)
body
ident = readFile(tmpFile)
이것은 main.nim어설 션 오류없이 실행되지만 출력은
hello1
tmpFile에서 다음을 참조하십시오.
hello2
ciao3
답변
3 Clonk Sep 23 2020 at 16:16
호출 reopen할 때에 쓰는에 변수 stdout를 다시 할당합니다 .FiletmpFile
출력을 시스템 STDOUT에 인쇄하려면 systel STDOUT에 쓰는 변수 stdout를 a 에 다시 할당해야합니다 File.
따라서 대답은 Linux와 Windows간에 다릅니다.
Linux의 경우이를 수행하는 방법은 dup 및 dup2 C 함수를 stdout사용 하여 파일 설명자를 복제하고 다른 파일을 사용하는 것입니다 (따라서 stdout을 복원 할 수 있음). dup과 dup2는 system/ioNim 에 없기 때문에 unistd.h.
예를 들면 다음과 같습니다.
#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()