I am just exploring Zig, so perhaps this is an obvious newbie mistake. I couldn’t find any questions resembling it, so here I am to ask:
is it possible?
As part of learning the language I thought I would test the C ABI by writing a small Zig library and calling it from Raku. It works perfectly with the basic add
from the default zig init-lib
!
But if I want to pass a struct, I’ve got issues. Raku’s FFI allows for definitions of classes with native representations. It expects the resultant objects to be referenced by pointer in the signatures of called C functions. So I can’t conform to the pattern of returning a struct directly, which is how I saw some Zig code doing it. And obviously we can’t hand it back a pointer to something just created on the stack.
Trying to allocate leads to the following situation:
src/main.zig:21:12: error: expected type '*main.Reality', found 'error{OutOfMemory}'
return try allocator.create(Reality);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/main.zig:20:25: note: function cannot return an error
export fn get_reality() *Reality {
^~~~~~~~
Here is the code:
const std = @import("std");
const testing = std.testing;
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
var allocator = gpa.allocator();
const Allocator = std.mem.Allocator;
export fn add(a: i32, b: i32) i32 {
return a + b;
}
pub const Reality = extern struct {
verses: u32 = 128,
fn snap(self: *Reality) void {
self.verses = self.verses / 2;
std.debug.print("SNAP!\n{} verses left in the multiverse!\n", .{ self.verses });
}
};
export fn get_reality() *Reality {
const result = try allocator.create(Reality);
result.* = .{ verses = 128 };
return result;
}
export fn do_snap(reality: *Reality) void {
reality.snap();
}
export fn destroy_reality(reality: *Reality) void {
allocator.destroy(reality);
}
test "basic add functionality" {
try testing.expect(add(3, 7) == 10);
const reality = get_reality();
defer destroy_reality(reality);
try testing.expect(reality.verses == 128);
do_snap(reality);
try testing.expect(reality.verses == 64);
}
I’ve tried a ton of variations on the above code but nothing has worked for me yet…
Finally, I just want to start by saying how impressed I am with Zig. I’ve only been playing around for a few days but it is really striking how quickly the basics can be learned. The depths of systems programming lay in wait, of course… but it’s great to finally feel a bit equipped to handle them.
Thanks in advance for your help!