I have the below zig library code:
// clib.zig
const std = @import("std");
const format = "Hello, {s} {s}!";
export fn joinStringsSize(firstname: [*:0]const u8, lastname: [*:0]const u8) u64 {
return std.fmt.count(format, .{ firstname, lastname });
}
// Returns the number of bytes written, or 0 if there was not enough space.
export fn joinStrings(buf_ptr: [*]u8, buf_len: usize, firstname: [*:0]const u8, lastname: [*:0]const u8) u64 {
var buf = buf_ptr[0..buf_len];
const written = std.fmt.bufPrint(buf, format, .{ firstname, lastname }) catch return 0;
return written.len;
}
And compiled it as: $ zig build-lib -dynamic clib.zig
Then I wrote the header file as :
// clib.h
uint64_t joinStringsSize(const char* firstname, const char* lastname);
uint64_t joinStrings(uint8_t* buf_ptr, size_t buf_len, const char* firstname, const char* lastname);
Which I assume is equivalent to the functions used in the library:
fn joinStringsSize(firstname: [*:0]const u8, lastname: [*:0]const u8) u64
fn joinStrings(buf_ptr: [*]u8, buf_len: usize, firstname: [*:0]const u8, lastname: [*:0]const u8) u64
And tried to consume this library using the below zig code:
// cmain.zig
const std = @import("std");
const c = @cImport({
@cInclude("clib.h");
});
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{ .verbose_log = true }){};
defer {
if (gpa.deinit() == .ok) {
std.debug.print("Memory has been managed correctly.\n", .{});
} else {
std.debug.print("Memory has not been managed correctly.\n", .{});
// CAN I ADD SOMETHING HERE TO SHOW ME MORE DEATILS ABOUT THE LEAKS IN MY CODE?
}
}
const allocator = gpa.allocator();
const firstname = "Hasan";
const lastname = "Yousef";
var buf = try allocator.alloc(u8, c.joinStringsSize(firstname, lastname));
defer allocator.free(buf);
const len = c.joinStrings(buf.ptr, buf.len, firstname, lastname);
const greetings = buf[0..len]; // not really necessary here, because we allocated the correct size from `joinStringsSize`
std.debug.print("Saved string: {s}\n", .{greetings});
}
And tried to run it using $ zig run -I . cmain.zig
I added -I .
to enforce linking to the clib.h
file that is existing in the same folder of the cmain.zig
.
But I got the error:
$ zig run -I . cmain.zig
cmain.zig:2:11: error: C import failed
const c = @cImport({
^~~~~~~~
cmain.zig:2:11: note: libc headers not available; compilation does not link against libc
referenced by:
main: cmain.zig:20:39
callMain: /usr/lib/zig/std/start.zig:574:32
remaining reference traces hidden; use '-freference-trace' to see all reference traces
./clib.h:8:40: error: unknown type name 'size_t'
uint64_t joinStrings(uint8_t* buf_ptr, size_t buf_len, const char* firstname, const char* lastname);
Not sure if libc
means Igcc/clang
is not installed, but I already have it:
$ ldconfig -p | grep libc.so libc.so.6 (libc6,x86-64) => /usr/lib/libc.so.6
libc.so.6 (libc6) => /usr/lib32/libc.so.6
$ gcc --version
gcc (GCC) 13.2.1 20230801
Copyright (C) 2023 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ clang --version
clang version 16.0.6
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
libc
is installed on your system, but you didn't tell zig
to use it.
zig run -I . cmain.zig -lc