I recently tried to learn how to use zig to interact with c(I have no experience with c), and used the miniaudio library as a demo.
And i encountered some errors, but I don’t know if it was caused by incorrect usage of zig build. I hope someone with experience can guide me. Thank you very much.
src dir structure
src
├── c
│ ├── miniaudio.c
│ └── miniaudio.h
└── main.zig
main.zig
const std = @import("std");
const builtin = @import("builtin");
const log = std.log;
const ma = @cImport({
@cInclude("miniaudio.h");
});
pub const std_options = .{
.log_level = switch (builtin.mode) {
.Debug => .debug,
else => .info,
},
};
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
// read file path from commandline args
//
var args = try std.process.argsWithAllocator(allocator);
defer args.deinit();
_ = args.next();
const sound_file_path = args.next() orelse return error.ArgsNotFound;
log.info("song file path: {s}", .{sound_file_path});
// engine init
//
const engine = try allocator.create(ma.ma_engine);
defer allocator.destroy(engine);
if (ma.ma_engine_init(null, engine) != ma.MA_SUCCESS) {
return error.MAEngineInit;
}
defer ma.ma_engine_uninit(engine);
// sound init
//
const sound = try allocator.create(ma.ma_sound);
defer allocator.destroy(sound);
const flags = ma.MA_SOUND_FLAG_DECODE;
if (ma.ma_sound_init_from_file(engine, sound_file_path, flags, null, null, sound) != ma.MA_SUCCESS) {
return error.MASoundInitFile;
}
// sound start
//
if (ma.ma_sound_start(sound) != ma.MA_SUCCESS) {
return error.MASoundStart;
}
}
build.zig
const std = @import("std");
const miniaudio_header_dir = "src/c";
const miniaudio_src_file = "src/c/miniaudio.c";
const main_file = "src/main.zig";
const test_file = "src/main.zig";
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
// configure and install exe
//
const exe = b.addExecutable(.{
.name = "miniaudio.zig",
.root_source_file = b.path(main_file),
.target = target,
.optimize = optimize,
});
exe.addCSourceFile(.{ .file = .{
.path = miniaudio_src_file,
}, .flags = &.{} });
exe.addIncludePath(.{ .path = miniaudio_header_dir });
exe.linkLibC();
if (target.result.os.tag == .linux) {
exe.linkSystemLibrary("pthread");
exe.linkSystemLibrary("m");
exe.linkSystemLibrary("dl");
}
b.installArtifact(exe);
// run
//
const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| {
run_cmd.addArgs(args);
}
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
// tests
//
const unit_tests = b.addTest(.{
.root_source_file = .{ .path = test_file },
.target = target,
.optimize = optimize,
});
const run_unit_tests = b.addRunArtifact(unit_tests);
const test_step = b.step("test", "Run unit tests");
test_step.dependOn(&run_unit_tests.step);
}
run app
╰─❯ zig build run -- test.mp3
info: song file path: test.mp3
Illegal instruction at address 0xba8658
E:\code\me\test-zig\miniaudio.zig\src\c\miniaudio.h:67134:0: 0xba6fef in ma_hash_string_32 (miniaudio.obj)
return ma_hash_32(str, (int)strlen(str), MA_DEFAULT_HASH_SEED);
E:\code\me\test-zig\miniaudio.zig\src\c\miniaudio.h:68484:0: 0xab31a4 in ma_resource_manager_data_buffer_node_acquire (miniaudio.obj)
hashedName32 = ma_hash_string_32(pFilePath);
E:\code\me\test-zig\miniaudio.zig\src\c\miniaudio.h:68818:0: 0xaae6b7 in ma_resource_manager_data_buffer_init_ex_internal (miniaudio.obj)
result = ma_resource_manager_data_buffer_node_acquire(pResourceManager, pConfig->pFilePath, pConfig->pFilePathW, hashedName32, flags, NULL, notifications.init.pFence, notifications.done.pFence, &pDataBufferNode);
E:\code\me\test-zig\miniaudio.zig\src\c\miniaudio.h:68935:0: 0xaae069 in ma_resource_manager_data_buffer_init_ex (miniaudio.obj)
return ma_resource_manager_data_buffer_init_ex_internal(pResourceManager, pConfig, 0, pDataBuffer);
E:\code\me\test-zig\miniaudio.zig\src\c\miniaudio.h:70188:0: 0xab8d32 in ma_resource_manager_data_source_init_ex (miniaudio.obj)
return ma_resource_manager_data_buffer_init_ex(pResourceManager, pConfig, &pDataSource->backend.buffer);
E:\code\me\test-zig\miniaudio.zig\src\c\miniaudio.h:75920:0: 0xad2ea9 in ma_sound_init_from_file_internal (miniaudio.obj)
result = ma_resource_manager_data_source_init_ex(pEngine->pResourceManager, &resourceManagerDataSourceConfig, pSound->pResourceManagerDataSource);
E:\code\me\test-zig\miniaudio.zig\src\c\miniaudio.h:76064:0: 0xad45b2 in ma_sound_init_ex (miniaudio.obj)
return ma_sound_init_from_file_internal(pEngine, pConfig, pSound);
E:\code\me\test-zig\miniaudio.zig\src\c\miniaudio.h:75960:0: 0xad21ad in ma_sound_init_from_file (miniaudio.obj)
return ma_sound_init_ex(pEngine, &config, pSound);
E:\code\me\test-zig\miniaudio.zig\src\main.zig:42:35: 0xc7fef5 in main (miniaudio.zig.exe.obj)
if (ma.ma_sound_init_from_file(engine, sound_file_path, flags, null, null, sound) != ma.MA_SUCCESS) {
^
E:\scoop\global\apps\zig-dev\0.13.0-dev.30\lib\std\start.zig:484:5: 0xc808fa in main (miniaudio.zig.exe.obj)
return callMainWithArgs(@as(usize, @intCast(c_argc)), @as([*][*:0]u8, @ptrCast(c_argv)), envp);
^
E:\scoop\global\apps\zig-dev\0.13.0-dev.30\lib\libc\mingw\crt\crtexe.c:267:0: 0xd082e4 in __tmainCRTStartup (crt2.obj)
mainret = _tmain (argc, argv, envp);
E:\scoop\global\apps\zig-dev\0.13.0-dev.30\lib\libc\mingw\crt\crtexe.c:188:0: 0xd0833b in mainCRTStartup (crt2.obj)
ret = __tmainCRTStartup ();
???:?:?: 0x7ffe9047257c in ??? (KERNEL32.DLL)
???:?:?: 0x7ffe918aaa47 in ??? (ntdll.dll)