Closed18

zigを勉強してるwebフロントエンドエンジニアのメモ

u-yasu-yas

自分がzig関連で調べて参考になったサイトを列挙するので皆さんはぜひそれ参考にがんばってください・・・もしできたら教えてください。


reference: https://ziglang.org/documentation/master/
情報が少なすぎるので基本これ見て手元で動かしていく

wiki: https://github.com/ziglang/zig/wiki/Community
色々参考サイトがまとまってる

ブログ記事: https://zig.news/
zigに関するブログ記事がまとまってる。zigの作者の投稿に役に立つ記事が多かった
例: https://zig.news/kristoff/compile-a-c-c-project-with-zig-368j

チュートリアル: https://ziglearn.org/

zenn本: https://zenn.dev/ousttrue/books/b2ec4e93bdc5c4/viewer/e13c06
本家のサイトだと硬いのでゆるく読めておすすめです


ここから下は中身なし

とりあえず目標を作らないとどうしようもないので

第1目標: 超簡単なコレクション操作系の処理を作ってwebassemblyとしてビルド、それをフロントエンドから呼び出す

第2目標: 画像変換処理を作る。具体的には https://github.com/lovell/sharp の一部の機能だけをzigで再現する

u-yasu-yas

Q.なぜRustじゃないの?
A. zigのほうがロマンを感じたので

正直99%の人はRust使いこなせるようにしたほうが良い

u-yasu-yas

ダウンロードページから温かみのあるインスコしました

https://ziglang.org/ja/download/

バイナリを移動させるだけですぐ使えるようになるのは便利

正確にはdownloadページからインスコしたフォルダごと移動させてpathを通さないとだめ。zigバイナリだけを移動させると

unable to find zig installation directory: FileNotFound

というエラーが出る

参考: https://cvo-23052022.fly.dev/unable-to-find-zig-installation-directory-filenotfound/

u-yasu-yas

https://zig.news/kristoff/what-s-a-string-literal-in-zig-31e9

https://ziglang.org/documentation/master/#toc-String-Literals-and-Unicode-Code-Point-Literals

zigではstring型がないのね

[*:0]u8 がstringになるのね

char型みたいなのはないのね

理屈としては理解できるけど、初見だとわからなかった・・・

const std = @import("std");

pub fn main() !void {
    const args: ([][*:0]u8) = std.os.argv;
    const stdout = std.io.getStdOut().writer();
    const first_arg: [*:0]u8 = args[1];

    // zig run src/main.zig -- aaaa
    // output: aaaa
    try stdout.print("{s}\n", .{first_arg});
}
u-yasu-yas

コマンドライン引数に指定されたファイルの中身を読み取って配列に入れて適当に出力するコード

const std = @import("std");

// https://github.com/ziglang/zig/blob/master/test/behavior/const_slice_child.zig#L37-L41
fn strlen(ptr: [*]const u8) usize {
    var count: usize = 0;
    while (ptr[count] != 0) : (count += 1) {}
    return count;
}
pub fn main() !void {
    // コマンドライン引数を読み取る
    const args: ([][*:0]u8) = std.os.argv;
    // 最初の引数
    const first_arg = args[1];

    // convert [*:0]u8 to []u8
    const first_arg_slice = first_arg[0..strlen(first_arg)];
   // fileの内容を取得する
    var file = try std.fs.cwd().openFile(first_arg_slice, .{});
    defer file.close();

    // fileのバイナリを格納する変数
    var buf: [1024]u8 = undefined;
    // ファイルの内容を変数に書き込む
    _ = try file.read(&buf);

    var stdout = std.io.getStdOut().writer();
    // printする
    try stdout.print("{d}", .{buf});
}

u-yasu-yas

@embedFileの引数に渡すファイルpathはcomptime時存在しているファイルじゃないとだめらしい
つまり、これだとだめ

const std = @import("std");

fn strlen(ptr: [*]const u8) usize {
    var count: usize = 0;
    while (ptr[count] != 0) : (count += 1) {}
    return count;
}
pub fn main() !void {
    const args: ([][*:0]u8) = std.os.argv;
    const first_arg = args[1];

    // convert [*:0]u8 to []u8
    const first_arg_slice = first_arg[0..strlen(first_arg)];
    var file = try @embedFile(first_arg_slice);

    const stdout = std.io.getStdOut().writer();
    try stdout.print("{d}", .{file});
}
❯ zig run src/main.zig -- src/feaf.png
src/main.zig:14:31: error: unable to resolve comptime value
    var file = try @embedFile(first_arg_slice);
                              ^~~~~~~~~~~~~~~
src/main.zig:14:31: note: file path name must be comptime-known
referenced by:
    callMain: /usr/local/zig/lib/std/start.zig:608:32
    initEventLoopAndCallMain: /usr/local/zig/lib/std/start.zig:542:34
    remaining reference traces hidden; use '-freference-trace' to see all reference traces


u-yasu-yas

適当に作ってみたけど mapみたいな関数をzigで作るの厳しそう
※というよりそもそもzigのgenericがよくわからない・・・anytypeは実行時型推論、typeはcomptime時型推論っていうのはわかるけど戻り値にanytypeを入れることができない・・・そういうものかも

const std = @import("std");
const testing = std.testing;
const Arraylist = std.ArrayList;
const allocator = std.mem.Allocator;

// javascript map function
export fn map(array: anytype, callback: fn (elem: anytype) type) void {
    var list = Arraylist(type).init(allocator);

    for (array) |elem| {
        var result = callback(elem);
        try list.addOne(result);
    }
    return list;
}
src/main.zig:7:15: error: generic parameters not allowed in function with calling convention 'C'
export fn map(array: anytype, callback: fn (elem: anytype) type) void {
u-yasu-yas

第1目標: 超簡単なコレクション操作系の処理を作ってwebassemblyとしてビルド、それをフロントエンドから呼び出す

失敗!!!!!!!!!

u-yasu-yas

第2目標: 画像変換処理を作る。具体的には https://github.com/lovell/sharp の一部の機能だけをzigで再現する

をやろう・・・

pngやjpegの画像をwebpに変換できるようにする

webpへの変換を時前実装したら死ぬので大人しくlibwebpを呼び出すようにする

https://github.com/webmproject/libwebp/tree/v1.3.1

zigは簡単にC系のプログラムをリンクさせることができるのでいい感じにできるようにしたい

u-yasu-yas

上記の記事とソースコードを見て思ったのですがソースファイルと一緒にビルドしようとしたけどC系のライブラリはそんなことするのではなく

apt install webpとかbrew install webpをして、一緒にくっついてくるheaderファイルをincludeすればいいのね

このスクラップは2023/07/05にクローズされました