diff --git a/src/class.zig b/src/class.zig index 738b42f..d5f4ff2 100644 --- a/src/class.zig +++ b/src/class.zig @@ -63,14 +63,14 @@ pub const Class = struct { /// allows adding new methods; returns true on success. // imp should be a function with C calling convention // 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; assert(fn_info.calling_convention == .C); assert(fn_info.is_var_args == false); assert(fn_info.params.len >= 2); assert(fn_info.params[0].type == c.id); 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); 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); 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); +}