Print to console with Chez Scheme and Windows console API.

saitoatsushi profile image 齊藤敦志 ・2 min read

On Windows, when print character to console via standard output, the character is interpret in current codepage. If encoding of a inner character string is different with current codepage, mojibake will happen. Encoding conversion is necessary.

And, it is impossible to print character that be not contained current codepage via standard output.

For print all unicode characters, we can use console API rather than standard output.

I made console output library with Chez Scheme's foreign interface and console API on Windows.

(library (console-port)
  (export open-console-output-port)
  (import (chezscheme))

  (define dummy (begin (load-shared-object "kernel32.dll") 1))

  (define-ftype handle void*)

  (define open-existing 3)

  (define create-file
    (foreign-procedure __stdcall "CreateFileW"
      (wstring unsigned-32 unsigned-32 void* unsigned-32 unsigned-32 void*)

  (define file-share-write 2)

  (define generic-write #x40000000)

  (define (get-active-console-buffer)
    (create-file "CONOUT$" generic-write file-share-write 0 open-existing 0 0))

  (define write-console
    (foreign-procedure __stdcall "WriteConsoleW"
      (void* wstring unsigned-32 u32* void*)

  (define (open-console-output-port)
    (let ((output-handle (get-active-console-buffer))
          (vsize (make-bytevector 4)))
      (define (write-to-console string start count)
        (let ((str (substring string start (+ start count))))
          (write-console output-handle str count vsize 0)
      (make-custom-textual-output-port "console" write-to-console #f #f #f)))
(import (rnrs)

(let ((port (open-console-output-port)))
  (display "あいうえお\nかきくけこ\n" port)
  (display "♘♞♙♕♟♝♜♗♛♚♖♔" port)
  (flush-output-port port)) ;; Do not forget the flash!!

My windows computer is setted CP932. CP932 do not contain chess characters. But, it is printable by console API.

Unicode character printable


Editor guide