zigを勉強してるwebフロントエンドエンジニアのメモ
自分が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で再現する
Q.なぜRustじゃないの?
A. zigのほうがロマンを感じたので
正直99%の人はRust使いこなせるようにしたほうが良い
brew install zig --HEAD
で最新版を取ってくる
取ってこようとしたらインスコできなかった
つい3日前に brew install zig --HEADできないようになってたっぽい。ぐぇ
ダウンロードページから温かみのあるインスコしました
バイナリを移動させるだけですぐ使えるようになるのは便利
正確にはdownloadページからインスコしたフォルダごと移動させてpathを通さないとだめ。zigバイナリだけを移動させると
unable to find zig installation directory: FileNotFound
というエラーが出る
参考: https://cvo-23052022.fly.dev/unable-to-find-zig-installation-directory-filenotfound/
上記の真似をしようとしたら、上記の手順は古くなってた
https://marketplace.visualstudio.com/items?itemName=ziglang.vscode-zigを インスコしてバージョンとpathの設定だけちゃんとやってればうまくいきました
参考の設定
ちゃんと補完も効いてた
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});
}
参考になる記事・・・!!!
コマンドライン引数に指定されたファイルの中身を読み取って配列に入れて適当に出力するコード
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});
}
こんなことしなくても組み込み関数があるっぽい
便利ー!!!
@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
適当に作ってみたけど 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 {
第1目標: 超簡単なコレクション操作系の処理を作ってwebassemblyとしてビルド、それをフロントエンドから呼び出す
失敗!!!!!!!!!
数日ゴニョゴニョしてましたがなんだかんだzig本体のソースコードが参考になりそう
第2目標: 画像変換処理を作る。具体的には https://github.com/lovell/sharp の一部の機能だけをzigで再現する
をやろう・・・
pngやjpegの画像をwebpに変換できるようにする
webpへの変換を時前実装したら死ぬので大人しくlibwebpを呼び出すようにする
zigは簡単にC系のプログラムをリンクさせることができるのでいい感じにできるようにしたい
参考
上記の記事とソースコードを見て思ったのですがソースファイルと一緒にビルドしようとしたけどC系のライブラリはそんなことするのではなく
apt install webp
とかbrew install webp
をして、一緒にくっついてくるheaderファイルをincludeすればいいのね
細かい型の辻褄合わせがとてもむずかしい・・・
[]const u8
[]u8
[]u8
[]const u8
const []u8
const [*]u8
*const []u8
しんどい