init
This commit is contained in:
158
README.md
Normal file
158
README.md
Normal file
@@ -0,0 +1,158 @@
|
||||
# zig interface helper
|
||||
|
||||
first why does this exist i didnt like having to write `*anyopaque` for all the functions that are in the implemention of an interface so i made wrapper do it for you. This now hides all the nasty polymorphism shenanigans within the interface where it belongs.
|
||||
Additionally it also allows you to use your implementation normally rather than having to pass it through the interface first.
|
||||
|
||||
# how does this lib work
|
||||
|
||||
This lib basically removes the annoying conversion back to the original type in your implementation and instead does that conversion in a wrapper functions instead. This should now allow you to write more code and less boilerplate.
|
||||
|
||||
In essence all this lib does is
|
||||
```zig
|
||||
...
|
||||
somefn : *const fn(*anyopaque, u8, []const u8) !?f32
|
||||
...
|
||||
```
|
||||
to using (`VtableFn`)
|
||||
```zig
|
||||
...
|
||||
somefn : *const fn(struct {*anyopaque, u8, []const u8}) !?f32
|
||||
...
|
||||
```
|
||||
|
||||
and your implementation functions from
|
||||
|
||||
```zig
|
||||
...
|
||||
pub fn area(self : Self, times : f32) f32 {
|
||||
return self.h * self.w * times;
|
||||
}
|
||||
...
|
||||
```
|
||||
to using (`ToVtableFn`)
|
||||
```zig
|
||||
pub fn areaWrapper(args : struct {*anyopaque, f32}) f32 {
|
||||
const self : orignal_type = @ptrCast(@alignCast(args[0]));
|
||||
|
||||
return @call(.auto, area, {
|
||||
self,
|
||||
args[1],
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
# example
|
||||
|
||||
```zig
|
||||
|
||||
const Iface = @import("zig_interface_testing");
|
||||
|
||||
|
||||
// implemention
|
||||
const Circle = struct {
|
||||
const Self = @This();
|
||||
radius: f32,
|
||||
|
||||
pub fn init(r: f32) Self {
|
||||
return Self{
|
||||
.radius = r,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn perimeter(self: Self) f32 {
|
||||
return std.math.pi * self.radius * 2;
|
||||
}
|
||||
|
||||
pub fn area(self: Self) f32 {
|
||||
return std.math.pi * self.radius * self.radius;
|
||||
}
|
||||
|
||||
pub fn format(
|
||||
self: Self,
|
||||
writer: *std.Io.Writer,
|
||||
) !void {
|
||||
try writer.print("Circle : {}", .{self.radius});
|
||||
}
|
||||
};
|
||||
|
||||
// implemention
|
||||
const Rect = struct {
|
||||
const Self = @This();
|
||||
|
||||
w: f32,
|
||||
h: f32,
|
||||
|
||||
pub fn init(w: f32, h: f32) Self {
|
||||
return Self{
|
||||
.w = w,
|
||||
.h = h,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn perimeter(self: Rect) f32 {
|
||||
return self.h * 2 + self.w * 2;
|
||||
}
|
||||
|
||||
pub fn area(self: Self) f32 {
|
||||
return self.h * self.w;
|
||||
}
|
||||
|
||||
pub fn format(
|
||||
self: Self,
|
||||
writer: *std.Io.Writer,
|
||||
) !void {
|
||||
try writer.print("sqaure : {}, {}", .{ self.h, self.w });
|
||||
}
|
||||
};
|
||||
|
||||
// interface
|
||||
const Shape = struct {
|
||||
const Self = @This();
|
||||
data: *anyopaque,
|
||||
vtable: *const Vtable,
|
||||
|
||||
// create your vtable
|
||||
const Vtable = struct {
|
||||
// convert your vtable functions with Iface.VtableFn
|
||||
perimeter_fn: *const Iface.VtableFn(fn (*anyopaque) f32), // -> *const fn (tuple) returnType
|
||||
area_fn: *const Iface.VtableFn(fn (*anyopaque) f32),
|
||||
format_fn: *const Iface.VtableFn(fn (self: *anyopaque, writer: *std.Io.Writer) anyerror!void),
|
||||
};
|
||||
|
||||
pub fn init(shape: anytype) Self {
|
||||
std.debug.print("shape : {*}\n", .{shape});
|
||||
const self = Self{
|
||||
.data = @ptrCast(shape),
|
||||
.vtable = &Vtable{
|
||||
// convert your implemation functions to that of the vtable
|
||||
.perimeter_fn = Iface.ToVtableFn(@field(@TypeOf(shape.*), "perimeter")),
|
||||
.area_fn = Iface.ToVtableFn(@field(@TypeOf(shape.*), "area")),
|
||||
.format_fn = Iface.ToVtableFn(@field(@TypeOf(shape.*), "format")),
|
||||
},
|
||||
};
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
pub fn perimeter(self: Self) f32 {
|
||||
// run them functions
|
||||
return self.vtable.perimeter_fn(.{self.data});
|
||||
}
|
||||
|
||||
pub fn area(self: Self) f32 {
|
||||
return self.vtable.area_fn(.{self.data});
|
||||
}
|
||||
|
||||
pub fn format(
|
||||
self: Self,
|
||||
writer: *std.Io.Writer,
|
||||
) !void {
|
||||
self.vtable.format_fn(.{ self.data, writer }) catch {
|
||||
return std.Io.Writer.Error.WriteFailed;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
```
|
||||
Reference in New Issue
Block a user