Refleksi Makro C di Zig
(jstrieb.github.io)Refleksi Makro C di Zig
-
Zig
- Zig adalah bahasa pemrograman baru yang berfokus pada pemrograman tingkat rendah dan sistem, serta sedang memantapkan posisinya sebagai bahasa yang dapat menggantikan C
- Saat ini masih dalam pengembangan, tetapi sudah digunakan oleh proyek seperti Bun dan TigerBeetle
- Salah satu fitur Zig yang paling mengesankan adalah interoperabilitasnya yang sangat baik dengan C
-
Memanggil pustaka eksternal
- Di Zig, pustaka eksternal dapat dipanggil dengan mudah
- Contoh kode:
const win = @import("std").os.windows; extern "user32" fn MessageBoxA(?win.HWND, [*:0]const u8, [*:0]const u8, u32,) callconv(win.WINAPI) i32; pub fn main() !void { _ = MessageBoxA(null, "world!", "Hello", 0); }
-
Mengimpor file header C
- Di Zig, file header C dapat diimpor dan digunakan seperti impor Zig biasa
- Contoh kode:
const win32 = @cImport({ @cInclude("windows.h"); @cInclude("winuser.h"); }); pub fn main() !void { _ = win32.MessageBoxA(null, "world!", "Hello", 0); }
-
Pemrograman Windows
- Aplikasi Windows pada umumnya memiliki fungsi main dan fungsi window procedure
- Fungsi main menginisialisasi aplikasi dan menjalankan loop yang meneruskan pesan ke window procedure
- Window procedure menerima dan menangani pesan
- Contoh kode:
const std = @import("std"); const windows = std.os.windows; const win32 = @cImport({ @cInclude("windows.h"); @cInclude("winuser.h"); }); var stdout: std.fs.File.Writer = undefined; pub export fn WindowProc(hwnd: win32.HWND, uMsg: c_uint, wParam: win32.WPARAM, lParam: win32.LPARAM) callconv(windows.WINAPI) win32.LRESULT { _ = switch (uMsg) { win32.WM_CLOSE => win32.DestroyWindow(hwnd), win32.WM_DESTROY => win32.PostQuitMessage(0), else => { stdout.print("Unknown window message: 0x{x:0>4}\n", .{uMsg}) catch undefined; }, }; return win32.DefWindowProcA(hwnd, uMsg, wParam, lParam); } pub export fn main(hInstance: win32.HINSTANCE) c_int { stdout = std.io.getStdOut().writer(); var class = std.mem.zeroes(win32.WNDCLASSEXA); class.cbSize = @sizeOf(win32.WNDCLASSEXA); class.style = win32.CS_VREDRAW | win32.CS_HREDRAW; class.hInstance = hInstance; class.lpszClassName = "Class"; class.lpfnWndProc = WindowProc; _ = win32.RegisterClassExA(&class); const hwnd = win32.CreateWindowExA(win32.WS_EX_CLIENTEDGE, "Class", "Window", win32.WS_OVERLAPPEDWINDOW, win32.CW_USEDEFAULT, win32.CW_USEDEFAULT, win32.CW_USEDEFAULT, win32.CW_USEDEFAULT, null, null, hInstance, null); _ = win32.ShowWindow(hwnd, win32.SW_NORMAL); _ = win32.UpdateWindow(hwnd); var message: win32.MSG = std.mem.zeroes(win32.MSG); while (win32.GetMessageA(&message, null, 0, 0) > 0) { _ = win32.TranslateMessage(&message); _ = win32.DispatchMessageA(&message); } return 0; }
-
Refleksi
- Memetakan makro C bisa menjadi pekerjaan yang merepotkan
- Di Zig, fungsi @typeInfo dapat digunakan untuk menampilkan field dan deklarasi struct
- Dengan ini, makro C dapat direfleksikan di Zig
- Contoh kode:
const window_messages = get_window_messages(); fn get_window_messages() [65536][:0]const u8 { var result: [65536][:0]const u8 = undefined; @setEvalBranchQuota(1000000); for (@typeInfo(win32).Struct.decls) |field| { if (field.name.len >= 3 and std.mem.eql(u8, field.name[0..3], "WM_")) { const value = @field(win32, field.name); result[value] = field.name; } } return result; } pub export fn WindowProc(hwnd: win32.HWND, uMsg: c_uint, wParam: win32.WPARAM, lParam: win32.LPARAM) callconv(windows.WINAPI) win32.LRESULT { _ = switch (uMsg) { win32.WM_CLOSE => win32.DestroyWindow(hwnd), win32.WM_DESTROY => win32.PostQuitMessage(0), else => { stdout.print("{s}: 0x{x:0>4}\n", .{ window_messages[uMsg], uMsg }) catch undefined; }, }; return win32.DefWindowProcA(hwnd, uMsg, wParam, lParam); }
-
Kesimpulan
- Zig memungkinkan fungsi-fungsi C dilakukan dengan lebih nyaman menggunakan struktur bahasa pemrograman yang lebih modern
- Zig menyertakan toolchain kompiler C sehingga dapat memasukkan deklarasi dari file header C dengan mulus
- Filosofi pragmatis Zig langsung terasa begitu mulai mempelajari bahasanya
- Desain Zig yang intuitif dan konsisten membantu meningkatkan produktivitas
Ringkasan GN⁺
- Zig adalah bahasa baru yang berfokus pada pemrograman tingkat rendah dan sistem, dengan interoperabilitas yang sangat baik dengan C
- Zig dapat mengimpor dan menggunakan file header C, serta merefleksikan makro C di dalam Zig
- Filosofi pragmatis dan desain Zig yang intuitif sangat membantu dalam mempelajari dan menggunakan bahasa ini
- Zig menyediakan jalur untuk memindahkan codebase C yang sudah ada ke Zig, sehingga mengatasi hambatan adopsi bahasa
1 komentar
Komentar Hacker News
Fitur
@cImportakan dihapusContoh kode:
Kode yang setara dalam bahasa D:
Kompiler menangani sisanya
Ada orang yang meminta sintaks khusus untuk mengimpor file C, tetapi kesederhanaan ini lebih baik
Saya ingin menyukai Zig, tetapi mengalami beberapa masalah
zig initmemiliki banyak kode yang tidak perluzig build-exe filename.zigPreprosesor Clang tidak diimplementasikan sebagai tahap pra-kompilasi yang terpisah
Saya menulis di blog tentang cara melakukan pekerjaan serupa di bahasa D menggunakan ImportC
Sepertinya setiap enum akan menambahkan setidaknya UINT16_MAX*sizeof(intptr_t) byte ke file executable
Definisi fungsinya terlihat sangat mudah dibaca
Saya suka situsnya