Open5

Zigのメモ

akio tanakaakio tanaka

StringHashMap snippet

test "StringHashMap" {
  var hash = std.StringHashMap(i32).init(std.testing.allocator);
  defer hash.deinit();

  try hash.put("test0", 0);
  try hash.put("test1", 1);

  var it = hash.iterator();
  while (it.next()) |entry| {
    std.debug.print("key={s}, value={d}\n", .{entry.key_ptr.*, entry.value_ptr.*});
  }

  try std.testing.expectEqual(@as(i32, 0), hash.get("test0").?);
  try std.testing.expectEqual(@as(i32, 1), hash.get("test1").?);
}
akio tanakaakio tanaka

usingnamespace

  • usingnamespace - documentation
  • Zigにおけるnamespaceはstruct, union, enum, opaque?
  • namespace内でpub宣言されたものを別のnamespaseで利用可能にする
  • mixin的な使い方
const std = @import("std");
const testing = std.testing;

test "usingnamespace" {

  const S = struct {
    usingnamespace @import("std");

    /// this property does not become a member in caller struct due to lack of `pub`
    const NOT_IN_NAMESPACE_NUM = 11;

    /// this property becomes a member with usingnamespace.
    pub const NUM =12;

    /// this property does not become a member in caller struct due to lack of `pub`
    fn notInNamespaceFunc() bool {
      return false;
    }

    /// this property becomes a member with usingnamespace.
    pub fn inNamespaceFunc() bool {
      return true;
    }
  };

  // caller struct for S.
  const T = struct {
    usingnamespace S;
  };

  // usingnamespace T;  // this statement can not be compiled.

  // you can use all members from S scope.
  try S.testing.expect(true);
  try S.testing.expectEqual(S.NOT_IN_NAMESPACE_NUM, 11);
  try S.testing.expectEqual(S.NUM, 12);
  try testing.expect(!S.notInNamespaceFunc());
  try testing.expect(S.inNamespaceFunc());

  // you can use only members with pub in S from T scope.
  // try testing.expectEqual(T.NOT_IN_NAMESPACE_NUM, 11);  // this statement can not be compiled.
  try testing.expectEqual(T.NUM, 12);
  // try testing.expect(!T.notInNamespaceFunc());  // this statement can not be compiled.
  try testing.expect(T.inNamespaceFunc());
}
akio tanakaakio tanaka

実行環境のOS種類の確認

const std = @import("std");
const builtin = @import("builtin");

test "confirm OS type" {
    const is_windows = builtin.os.tag == .windows;
    std.debug.print("is windows = {}\n", .{is_windows});

    const is_mac = builtin.os.tag == .macos;
    std.debug.print("is mac = {}\n", .{is_mac});

    const is_linux = builtin.os.tag == .linux;
    std.debug.print("is linux = {}\n", .{is_linux});

    std.debug.print("this os is {}\n", .{builtin.os.tag});
}
akio tanakaakio tanaka

コマンドライン引数

  • 下記コードの実行方法
    • ビルドして実行
      • ビルド例: $ zig build-exe main.zig -O Debug
      • 実行レイ: $ ./main.exe arg1 arg2
    • runコマンドで実行
      • 実行例: $ zig run main.zig -- arg1 arg2
const std = @import("std");
const process = std.process;


const Args = struct {
  const Self = @This();

  allocator: std.mem.Allocator,
  items: [][:0]u8,

  pub fn init(allocator: std.mem.Allocator) !Args {
    return Args{
      .allocator = allocator,
      .items = try process.argsAlloc(allocator),
    };
  }

  pub fn deinit(self: Self) void {
    defer process.argsFree(self.allocator, self.items);
  }

  pub fn print(self: Self) void {
    for (self.items) |item, i| {
      std.debug.print("arg[{d}]={s}\n", .{i, item});
    }
  }
};


pub fn main() !void {
  var gpa = std.heap.GeneralPurposeAllocator(.{}){};
  const allocator = gpa.allocator();
  defer std.debug.assert(!gpa.deinit());

  const args = try Args.init(allocator);
  defer args.deinit();
  args.print();

  // how to access individual arguments
  for (args.items) |item, i| {
    std.debug.print("args[{d}] from props={s}\n", .{i, item});
  }
}
akio tanakaakio tanaka

Windows向けVSCode上でのZigデバッグ環境構築 (初手)

Zigのインストール

  • chocolatelyでインストール可能
  • 管理者権限でコマンドプロンプトを起動してchoco install zig

VSCodeの設定

拡張機能

デバッグ環境

  • .vscode/launch.jsonの作成
    • program、cwd、symbolSearchPathは自分の環境にあったものを指定
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Debug exe",
      "type": "cppvsdbg",
      "request": "launch",
      "program": "${workspaceFolder}/zig-out/bin/init-exe.exe",
      "args": [],
      "stopAtEntry": false,
      "cwd": "${workspaceFolder}/zig-out/bin",
      "symbolSearchPath": "${workspaceFolder}/zig-out/bin",
      "environment": [],
      "externalConsole": false,
      "logging": {
          "moduleLoad": false
      },
    }
  ]
}
  • .vscode/tasks.jsonの作成
    • zig runzig testも設定したい
{
  "version": "2.0.0",
  "tasks": [
      {
          "label": "Build zig",
          "type": "shell",
          "command": "zig build",
          "group": "build",
          "options": {
              "cwd": "${workspaceFolder}"
          },
          "problemMatcher": []
      }
  ]
}

build.zigの設定

  • とりあえずziglearn.orgに記載されているもっとも単純なサンプルで作成
const Builder = @import("std").build.Builder;

pub fn build(b: *Builder) void {
    const target = b.standardTargetOptions(.{});
    const mode = b.standardReleaseOptions();

    const exe = b.addExecutable("init-exe", "src/main.zig");
    exe.setTarget(target);
    exe.setBuildMode(mode);
    exe.install();

    const run_cmd = exe.run();
    run_cmd.step.dependOn(b.getInstallStep());

    const run_step = b.step("run", "Run the app");
    run_step.dependOn(&run_cmd.step);
}

デバッグ実行

  • C/C++同様、ビルドで生成されたexeとデバッグ情報を基にデバッグ
    • zig build
    • F5もしくは「実行とデバッグ」ペインのタスク「Debug exe」(launch.jsonで指定したnameの値)でデバッグ実行

ビルド後のフォルダ構成:

+ .vscode
|     launch.sjon
|     tasks.json
|
+ src
|     main.zig
|
+ zig-cache
+ zig-out/bin
|     init-exe.exe
|     init-exe.pdb
|
+ build.zig

参考文献