📝

【Zig】Zigを試しながらのHow toメモ

2022/07/24に公開

Home ⚡ Zig Programming Language

何か新しい言語をインプットしながら、何か作りたいと思い、最近よく目にするZigが良さそうだったので、作りながら色々試してメモした内容になります。

試した環境

macOS Monterey バージョン12.1 Apple M1

環境構築

Macの場合Homebrewで導入可能みたいなので、そちらでインストールしてみたいと思います。

$ brew install zig

現時点でのインストールVersionは 0.9.1 でした。

$ zig version  
0.9.1

Hello world

何はともあれ、まずは Hello world やってみます。
まずは初期化して、そのまま実行してみます。

$ zig init-exe
$ zig build run
info: All your codebase are belong to us.

init-exe で以下が作成されます。

.
├── build.zig
└── src
    └── main.zig

build run でビルドと実行を行ってくれます。ビルドされた実行ファイルは zig-out/bin/xxxx に作成されてました。

次に Hello world を表示するためにsrc/main.zig を以下に修正します。
zig build runHello, world! が表示されればOKです。

const std = @import("std");

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();
    try stdout.print("Hello, {s}!\n", .{"world"});
}

import

別ファイルに定義した関数をimportして呼び出す場合、

funcs.zig
const std = @import("std");

pub fn debug() void {
  std.log.debug("funcs#debug call", .{});
}

↑ 呼び出したい関数に pub を付けます。

main.zig
const funcs = @import("funcs.zig");
const debug = funcs.debug;

pub fn main() void {
    debug();
}

あとは、呼び出す側で @import してやればOKです。

Allocator

Allocatorの種類

  • c_allocator
    • libcをリンクする場合に最適 (malloc_usable_sizeを使用する)
  • raw_c_allocator
    • malloc/freeを直接呼び出す (malloc_usable_sizeを使用しない)
  • page_allocator
    • メモリ割り当てと解放のたびに直接 syscall を呼び出す (Thread-safe and lock-free.)
  • HeapAllocator
    • windowsだけでしか使えない? 内部でHANDLEを使用
  • ArenaAllocator
    • 既存のアロケータをラップし、まとめて解放してくれる
  • FixedBufferAllocator
    • 固定長のバッファで事足りる場合に使用
  • LogToWriterAllocator
    • 他のアロケータを使う際に、指定したWriterにログを出力してくれる
  • LoggingAllocator
    • 他のアロケータを使う際に、std.log にログを出力してくれる

基本的な使い方

const std = @import("std");
const expect = std.testing.expect;

test "allocation" {
    const allocator = std.heap.page_allocator;

    const memory = try allocator.alloc(u8, 100);
    defer allocator.free(memory);

    try expect(memory.len == 100);
    try expect(@TypeOf(memory) == []u8);
}

LoggingAllocatorを使う場合

const std = @import("std");
const loggingAllocator = std.heap.loggingAllocator;

const allocator = loggingAllocator(std.heap.page_allocator).allocator();
// debug: alloc - success - len: 4602, ptr_align: 1, len_align: 1
// debug: free - len: 16384

ファイルの扱い

  • ファイルオープン/クローズ
const std = @import("std");

pub fn main() !void {
    const file_name = "xxxx";
    const file = try std.fs.cwd().openFile(fileName, .{});
    defer file.close();
}
  • ファイルサイズの取得
const std = @import("std");

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();

    const file_name = "xxxx";
    const file = try std.fs.cwd().openFile(fileName, .{});
    defer file.close();

    const file_size = try file.getEndPos();
    try stdout.print("file size: {d}\n", .{file_size});
}
  • ファイルのRead
const std = @import("std");

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();

    const file_name = "xxxx";
    const file = try std.fs.cwd().openFile(fileName, .{});
    defer file.close();

    const file_size = try file.getEndPos();
    try stdout.print("file size: {d}\n", .{file_size});

    var reader = std.io.bufferedReader(file.reader());
    var instream = reader.reader();

    const allocator = std.heap. page_allocator;
    const contents = try instream.readAllAlloc(allocator, file_size);
    defer allocator.free(contents);

    try stdout.print("read file value: {c}\n", .{contents});
}

複数の値をまとめてreturnしたい場合

pub fn getPosition() struct { start: i32, end: i32 } {
  const start = 1000;
  const end = 2000;
  return .{
    .start = start,
    .end = end
  };
}

structで束ねる様な形でreturnする

バッドノウハウ

brew install時に以下エラーに遭遇

Error: python@3.10: the bottle needs the Apple Command Line Tools to be installed.
  You can install them, if desired, with:
    xcode-select --install

You can try to install from source with:
  brew install --build-from-source python@3.10
Please note building from source is unsupported. You will encounter build
failures with some formulae. If you experience any issues please create pull
requests instead of asking for help on Homebrew's GitHub, Twitter or any other
official channels.

Python3が必要なのでメッセージ通り、xcode-select --install でコマンドラインツールをインストールして無事インストールできました。

$ python3 --version
Python 3.9.13

「もっとこうした方が〜」 などありましたら、アドバイス頂けると助かります!
また、メモが溜まったら記事にしたいと思います。

参考URL

Discussion