📖

Zig言語でUTF-8の日本語を出力(Windows)

2023/09/08に公開2

Zig から派生した Zen 言語では Windows 上でも UTF-8 で書かれたソース(文字列)をなんの手を加えることもなく、コンソールに表示させることができますが、Zig for Windows では、コマンドプロンプトで予め「chcp 65001」としてUTF-8モードにしておかないと文字化けします。

以下のソースは、Zen言語で自動的に追加される「SetConsoleOutputCP」関数(Win32 API)を手動で追加したものです。mainの先頭で一回呼んでおけば、それ以降のコンソール出力がUTF-8を正常に受け付けるようになります。(chcp 932 の状態でも表示されます。また、chcp 932 の状態でも韓国語やアラビア語も表示できます)

main.zig
const std = @import("std");
const windows = @import("std").os.windows;
const WINAPI = windows.WINAPI;
const BOOL = windows.BOOL;
const UINT = windows.UINT;

extern "kernel32" fn SetConsoleOutputCP(wCodePageID: UINT) callconv(WINAPI) BOOL;

pub fn main() anyerror!void {
    _ = SetConsoleOutputCP(65001);
    std.log.info("Zig の道へようこそ。\n道案内はこちらからどうぞ:\nhttps://ziglang.org/ja/\n", .{});
}

英語圏以外(でかつ Windowsのコンソールアプリ)なら必須の処理なので Zen 言語のように処理系が隠蔽してくれてもよさげに思いますが、「隠された処理」を嫌う Zig では取り込んでもらうのは無理かもしれません。

せめて、Linux や macOS とソースを同一化するために、「SetConsoleOutputCP」関数の宣言と呼び出しを Windows でない場合には削除したいのですが、どうすればよいのかわかりません。もしわかる人がいたら教えてください。

それでゃ!

Discussion

JavaCommonsJavaCommons

ktz_alias さん、ありがとうございます。
以下のコードで、Windows上とUbuntu上で同一のコードで日本語(UTF-8)を出力できました。

const builtin = @import("builtin");
const std = @import("std");
const windows = @import("std").os.windows;
const WINAPI = windows.WINAPI;
const BOOL = windows.BOOL;
const UINT = windows.UINT;

extern "kernel32" fn SetConsoleOutputCP(wCodePageID: UINT) callconv(WINAPI) BOOL;

pub fn main() anyerror!void {
    switch (builtin.os.tag) {
        .windows => _ = SetConsoleOutputCP(65001),
        else => {}
    }
    std.log.info("Zig の道へようこそ。\n道案内はこちらからどうぞ:\nhttps://ziglang.org/ja/\n", .{});
}