fix!: addMethod now passes errors it receives; added test

This commit is contained in:
Rylee Lyman 2023-10-21 08:51:58 -04:00
parent 98597c6903
commit bca05e03d3

View file

@ -63,14 +63,14 @@ pub const Class = struct {
/// allows adding new methods; returns true on success. /// allows adding new methods; returns true on success.
// imp should be a function with C calling convention // imp should be a function with C calling convention
// whose first two arguments are a `c.id` and a `c.SEL`. // whose first two arguments are a `c.id` and a `c.SEL`.
pub fn addMethod(self: Class, name: [:0]const u8, imp: anytype) bool { pub fn addMethod(self: Class, name: [:0]const u8, imp: anytype) !bool {
const fn_info = @typeInfo(@TypeOf(imp)).Fn; const fn_info = @typeInfo(@TypeOf(imp)).Fn;
assert(fn_info.calling_convention == .C); assert(fn_info.calling_convention == .C);
assert(fn_info.is_var_args == false); assert(fn_info.is_var_args == false);
assert(fn_info.params.len >= 2); assert(fn_info.params.len >= 2);
assert(fn_info.params[0].type == c.id); assert(fn_info.params[0].type == c.id);
assert(fn_info.params[1].type == c.SEL); assert(fn_info.params[1].type == c.SEL);
const str = objc.encodeFn(fn_info.return_type.?, fn_info.params) catch @panic("OOM!"); const str = try objc.createFnSignature(fn_info.return_type.?, fn_info.params);
defer std.heap.raw_c_allocator.free(str); defer std.heap.raw_c_allocator.free(str);
return c.class_addMethod(self.value, objc.sel(name).value, @ptrCast(&imp), str.ptr); return c.class_addMethod(self.value, objc.sel(name).value, @ptrCast(&imp), str.ptr);
} }
@ -195,3 +195,23 @@ test "Ivars" {
const slice = std.mem.sliceTo(my_ivar.getProperty([*c]const u8, "UTF8String"), 0); const slice = std.mem.sliceTo(my_ivar.getProperty([*c]const u8, "UTF8String"), 0);
try testing.expectEqualSlices(u8, "69---nice", slice); try testing.expectEqualSlices(u8, "69---nice", slice);
} }
test "addMethod" {
const testing = std.testing;
const My_Class = setup: {
const My_Class = allocateClassPair(objc.getClass("NSObject").?, "my_class").?;
defer registerClassPair(My_Class);
std.debug.assert(try My_Class.addMethod("my_addition", struct {
fn imp(target: objc.c.id, sel: objc.c.SEL, a: i32, b: i32) callconv(.C) i32 {
_ = sel;
_ = target;
return a + b;
}
}.imp));
break :setup My_Class;
};
const result = My_Class.msgSend(objc.Object, "alloc", .{})
.msgSend(objc.Object, "init", .{})
.msgSend(i32, "my_addition", .{ @as(i32, 2), @as(i32, 3) });
try testing.expectEqual(@as(i32, 5), result);
}