Skip to content

Commit

Permalink
Support stack and global blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
mjbshaw committed Aug 18, 2024
1 parent a4f91f7 commit c562628
Show file tree
Hide file tree
Showing 6 changed files with 265 additions and 286 deletions.
40 changes: 6 additions & 34 deletions generator.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1283,7 +1283,6 @@ fn Generator(comptime WriterType: type) type {
try self.writer.print(") ", .{});
try self.generateType(method.return_type);
try self.writer.print(" {{\n", .{});
try self.generateBlockHelpers(method);
try self.writer.writeAll(" return @as(");
try self.generateObjcSignature(method);
try self.writer.writeAll(", @ptrCast(&c.objc_msgSend))(");
Expand Down Expand Up @@ -1330,45 +1329,22 @@ fn Generator(comptime WriterType: type) type {

fn generateMethodParam(self: *Self, param: Param) !void {
if (getBlockType(param)) |f| {
try self.writer.writeAll("context: anytype, comptime ");
try self.writer.print("{s}_: ", .{param.name});
try self.writer.writeAll("fn (ctx: @TypeOf(context)");
try self.writer.print("{s}_: *ns.Block(fn (", .{param.name});
var first = true;
for (f.params.items) |param_ty| {
try self.writer.writeAll(", _: ");
if (!first) try self.writer.writeAll(", ");
first = false;
try self.generateType(param_ty);
}
try self.writer.writeAll(") ");
try self.generateType(f.return_type.*);
try self.writer.writeByte(')');
} else {
try self.writer.print("{s}_: ", .{param.name});
try self.generateType(param.ty);
}
}

fn generateBlockHelpers(self: *Self, method: Method) !void {
for (method.params.items) |param| {
if (getBlockType(param)) |f| {
try self.writer.writeAll(" const Literal = ns.BlockLiteral(@TypeOf(context));\n");
try self.writer.writeAll(" const Helper = struct {\n");
try self.writer.writeAll(" pub fn cCallback(literal: *Literal");
for (f.params.items, 0..) |param_ty, i| {
try self.writer.print(", a{d}: ", .{i});
try self.generateType(param_ty);
}
try self.writer.writeAll(") callconv(.C) void {\n");
try self.writer.print(" {s}_(literal.context", .{param.name});
for (0..f.params.items.len) |i| {
try self.writer.print(", a{d}", .{i});
}
try self.writer.writeAll(");\n");
try self.writer.writeAll(" }\n");
try self.writer.writeAll(" };\n");
try self.writer.writeAll(" const descriptor = ns.BlockDescriptor{ .reserved = 0, .size = @sizeOf(Literal) };\n");
try self.writer.writeAll(" const block = Literal{ .isa = _NSConcreteStackBlock, .flags = 0, .reserved = 0, .invoke = @ptrCast(&Helper.cCallback), .descriptor = &descriptor, .context = context };\n");
}
}
}

fn generateObjcSignature(self: *Self, method: Method) !void {
try self.writer.writeAll("*const fn (");
if (method.instance) {
Expand Down Expand Up @@ -1400,11 +1376,7 @@ fn Generator(comptime WriterType: type) type {

for (method.params.items) |param| {
try self.writer.writeAll(", ");
if (getBlockType(param)) |_| {
try self.writer.writeAll("@ptrCast(&block)");
} else {
try self.writer.print("{s}_", .{param.name});
}
try self.writer.print("{s}_", .{param.name});
}
}

Expand Down
24 changes: 4 additions & 20 deletions src/avf_audio.zig
Original file line number Diff line number Diff line change
Expand Up @@ -96,16 +96,8 @@ pub const AVAudioSession = opaque {
pub fn setAllowHapticsAndSystemSoundsDuringRecording_error(self_: *T, inValue_: bool, outError_: ?*?*ns.Error) bool {
return @as(*const fn (*T, *c.objc_selector, bool, ?*?*ns.Error) callconv(.C) bool, @ptrCast(&c.objc_msgSend))(self_, sel_setAllowHapticsAndSystemSoundsDuringRecording_error_, inValue_, outError_);
}
pub fn requestRecordPermission(self_: *T, context: anytype, comptime response_: fn (ctx: @TypeOf(context), _: bool) void) void {
const Literal = ns.BlockLiteral(@TypeOf(context));
const Helper = struct {
pub fn cCallback(literal: *Literal, a0: bool) callconv(.C) void {
response_(literal.context, a0);
}
};
const descriptor = ns.BlockDescriptor{ .reserved = 0, .size = @sizeOf(Literal) };
const block = Literal{ .isa = _NSConcreteStackBlock, .flags = 0, .reserved = 0, .invoke = @ptrCast(&Helper.cCallback), .descriptor = &descriptor, .context = context };
return @as(*const fn (*T, *c.objc_selector, *const anyopaque) callconv(.C) void, @ptrCast(&c.objc_msgSend))(self_, sel_requestRecordPermission_, @ptrCast(&block));
pub fn requestRecordPermission(self_: *T, response_: *ns.Block(fn (bool) void)) void {
return @as(*const fn (*T, *c.objc_selector, *const anyopaque) callconv(.C) void, @ptrCast(&c.objc_msgSend))(self_, sel_requestRecordPermission_, response_);
}
pub fn overrideOutputAudioPort_error(self_: *T, portOverride_: AVAudioSessionPortOverride, outError_: ?*?*ns.Error) bool {
return @as(*const fn (*T, *c.objc_selector, AVAudioSessionPortOverride, ?*?*ns.Error) callconv(.C) bool, @ptrCast(&c.objc_msgSend))(self_, sel_overrideOutputAudioPort_error_, portOverride_, outError_);
Expand Down Expand Up @@ -152,16 +144,8 @@ pub const AVAudioSession = opaque {
pub fn setActive_withOptions_error(self_: *T, active_: bool, options_: AVAudioSessionSetActiveOptions, outError_: ?*?*ns.Error) bool {
return @as(*const fn (*T, *c.objc_selector, bool, AVAudioSessionSetActiveOptions, ?*?*ns.Error) callconv(.C) bool, @ptrCast(&c.objc_msgSend))(self_, sel_setActive_withOptions_error_, active_, options_, outError_);
}
pub fn activateWithOptions_completionHandler(self_: *T, options_: AVAudioSessionActivationOptions, context: anytype, comptime handler_: fn (ctx: @TypeOf(context), _: bool, _: ?*ns.Error) void) void {
const Literal = ns.BlockLiteral(@TypeOf(context));
const Helper = struct {
pub fn cCallback(literal: *Literal, a0: bool, a1: ?*ns.Error) callconv(.C) void {
handler_(literal.context, a0, a1);
}
};
const descriptor = ns.BlockDescriptor{ .reserved = 0, .size = @sizeOf(Literal) };
const block = Literal{ .isa = _NSConcreteStackBlock, .flags = 0, .reserved = 0, .invoke = @ptrCast(&Helper.cCallback), .descriptor = &descriptor, .context = context };
return @as(*const fn (*T, *c.objc_selector, AVAudioSessionActivationOptions, *const anyopaque) callconv(.C) void, @ptrCast(&c.objc_msgSend))(self_, sel_activateWithOptions_completionHandler_, options_, @ptrCast(&block));
pub fn activateWithOptions_completionHandler(self_: *T, options_: AVAudioSessionActivationOptions, handler_: *ns.Block(fn (bool, ?*ns.Error) void)) void {
return @as(*const fn (*T, *c.objc_selector, AVAudioSessionActivationOptions, *const anyopaque) callconv(.C) void, @ptrCast(&c.objc_msgSend))(self_, sel_activateWithOptions_completionHandler_, options_, handler_);
}
pub fn setPreferredSampleRate_error(self_: *T, sampleRate_: f64, outError_: ?*?*ns.Error) bool {
return @as(*const fn (*T, *c.objc_selector, f64, ?*?*ns.Error) callconv(.C) bool, @ptrCast(&c.objc_msgSend))(self_, sel_setPreferredSampleRate_error_, sampleRate_, outError_);
Expand Down
60 changes: 13 additions & 47 deletions src/foundation.zig
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const c = @import("c.zig");
const system = @import("system.zig");

// ------------------------------------------------------------------------------------------------
// Types
Expand All @@ -14,23 +15,12 @@ pub const unichar = u16;
// ------------------------------------------------------------------------------------------------
// Blocks

extern const _NSConcreteStackBlock: *anyopaque;

pub const BlockDescriptor = extern struct {
reserved: c_ulong,
size: c_ulong,
};

pub fn BlockLiteral(comptime Context: type) type {
return extern struct {
isa: *anyopaque,
flags: c_int,
reserved: c_int,
invoke: *const fn () callconv(.C) void,
descriptor: *const BlockDescriptor,
context: Context,
};
}
pub const Block = system.Block;
pub const BlockLiteral = system.BlockLiteral;
pub const BlockLiteralWithSignature = system.BlockLiteralWithSignature;
pub const stackBlockLiteral = system.stackBlockLiteral;
pub const globalBlockLiteral = system.globalBlockLiteral;
pub const globalBlock = system.globalBlock;

// ------------------------------------------------------------------------------------------------
// Enumerations
Expand Down Expand Up @@ -1090,16 +1080,8 @@ pub const String = opaque {
// const block = Literal{ .isa = _NSConcreteStackBlock, .flags = 0, .reserved = 0, .invoke = @ptrCast(&Helper.cCallback), .descriptor = &descriptor, .context = context };
// return @as(*const fn (*T, *c.objc_selector, Range, StringEnumerationOptions, *const anyopaque) callconv(.C) void, @ptrCast(&c.objc_msgSend))(self_, sel_enumerateSubstringsInRange_options_usingBlock_, range_, opts_, @ptrCast(&block));
// }
pub fn enumerateLinesUsingBlock(self_: *T, context: anytype, comptime block_: fn (ctx: @TypeOf(context), _: *String, _: *bool) void) void {
const Literal = BlockLiteral(@TypeOf(context));
const Helper = struct {
pub fn cCallback(literal: *Literal, a0: *String, a1: *bool) callconv(.C) void {
block_(literal.context, a0, a1);
}
};
const descriptor = BlockDescriptor{ .reserved = 0, .size = @sizeOf(Literal) };
const block = Literal{ .isa = _NSConcreteStackBlock, .flags = 0, .reserved = 0, .invoke = @ptrCast(&Helper.cCallback), .descriptor = &descriptor, .context = context };
return @as(*const fn (*T, *c.objc_selector, *const anyopaque) callconv(.C) void, @ptrCast(&c.objc_msgSend))(self_, sel_enumerateLinesUsingBlock_, @ptrCast(&block));
pub fn enumerateLinesUsingBlock(self_: *T, block_: *Block(fn(*String, bool) void)) void {
return @as(*const fn (*T, *c.objc_selector, *const anyopaque) callconv(.C) void, @ptrCast(&c.objc_msgSend))(self_, sel_enumerateLinesUsingBlock_, block_);
}
pub fn dataUsingEncoding_allowLossyConversion(self_: *T, encoding_: StringEncoding, lossy_: bool) ?*Data {
return @as(*const fn (*T, *c.objc_selector, StringEncoding, bool) callconv(.C) ?*Data, @ptrCast(&c.objc_msgSend))(self_, sel_dataUsingEncoding_allowLossyConversion_, encoding_, lossy_);
Expand Down Expand Up @@ -1164,16 +1146,8 @@ pub const String = opaque {
pub fn initWithCharactersNoCopy_length_freeWhenDone(self_: *T, characters_: *unichar, length_: UInteger, freeBuffer_: bool) *T {
return @as(*const fn (*T, *c.objc_selector, *unichar, UInteger, bool) callconv(.C) *T, @ptrCast(&c.objc_msgSend))(self_, sel_initWithCharactersNoCopy_length_freeWhenDone_, characters_, length_, freeBuffer_);
}
pub fn initWithCharactersNoCopy_length_deallocator(self_: *T, chars_: *unichar, len_: UInteger, context: anytype, comptime deallocator_: fn (ctx: @TypeOf(context), _: *unichar, _: UInteger) void) *T {
const Literal = BlockLiteral(@TypeOf(context));
const Helper = struct {
pub fn cCallback(literal: *Literal, a0: *unichar, a1: UInteger) callconv(.C) void {
deallocator_(literal.context, a0, a1);
}
};
const descriptor = BlockDescriptor{ .reserved = 0, .size = @sizeOf(Literal) };
const block = Literal{ .isa = _NSConcreteStackBlock, .flags = 0, .reserved = 0, .invoke = @ptrCast(&Helper.cCallback), .descriptor = &descriptor, .context = context };
return @as(*const fn (*T, *c.objc_selector, *unichar, UInteger, *const anyopaque) callconv(.C) *T, @ptrCast(&c.objc_msgSend))(self_, sel_initWithCharactersNoCopy_length_deallocator_, chars_, len_, @ptrCast(&block));
pub fn initWithCharactersNoCopy_length_deallocator(self_: *T, chars_: *unichar, len_: UInteger, deallocator_: *Block(fn (*unichar, UInteger) void)) *T {
return @as(*const fn (*T, *c.objc_selector, *unichar, UInteger, *const anyopaque) callconv(.C) *T, @ptrCast(&c.objc_msgSend))(self_, sel_initWithCharactersNoCopy_length_deallocator_, chars_, len_, deallocator_);
}
pub fn initWithCharacters_length(self_: *T, characters_: *const unichar, length_: UInteger) *T {
return @as(*const fn (*T, *c.objc_selector, *const unichar, UInteger) callconv(.C) *T, @ptrCast(&c.objc_msgSend))(self_, sel_initWithCharacters_length_, characters_, length_);
Expand Down Expand Up @@ -1217,16 +1191,8 @@ pub const String = opaque {
pub fn initWithBytesNoCopy_length_encoding_freeWhenDone(self_: *T, bytes_: *anyopaque, len_: UInteger, encoding_: StringEncoding, freeBuffer_: bool) *T {
return @as(*const fn (*T, *c.objc_selector, *anyopaque, UInteger, StringEncoding, bool) callconv(.C) *T, @ptrCast(&c.objc_msgSend))(self_, sel_initWithBytesNoCopy_length_encoding_freeWhenDone_, bytes_, len_, encoding_, freeBuffer_);
}
pub fn initWithBytesNoCopy_length_encoding_deallocator(self_: *T, bytes_: *anyopaque, len_: UInteger, encoding_: StringEncoding, context: anytype, comptime deallocator_: fn (ctx: @TypeOf(context), _: *anyopaque, _: UInteger) void) *T {
const Literal = BlockLiteral(@TypeOf(context));
const Helper = struct {
pub fn cCallback(literal: *Literal, a0: *anyopaque, a1: UInteger) callconv(.C) void {
deallocator_(literal.context, a0, a1);
}
};
const descriptor = BlockDescriptor{ .reserved = 0, .size = @sizeOf(Literal) };
const block = Literal{ .isa = _NSConcreteStackBlock, .flags = 0, .reserved = 0, .invoke = @ptrCast(&Helper.cCallback), .descriptor = &descriptor, .context = context };
return @as(*const fn (*T, *c.objc_selector, *anyopaque, UInteger, StringEncoding, *const anyopaque) callconv(.C) *T, @ptrCast(&c.objc_msgSend))(self_, sel_initWithBytesNoCopy_length_encoding_deallocator_, bytes_, len_, encoding_, @ptrCast(&block));
pub fn initWithBytesNoCopy_length_encoding_deallocator(self_: *T, bytes_: *anyopaque, len_: UInteger, encoding_: StringEncoding, deallocator_: *Block(fn (*anyopaque, UInteger) void)) *T {
return @as(*const fn (*T, *c.objc_selector, *anyopaque, UInteger, StringEncoding, *const anyopaque) callconv(.C) *T, @ptrCast(&c.objc_msgSend))(self_, sel_initWithBytesNoCopy_length_encoding_deallocator_, bytes_, len_, encoding_, deallocator_);
}
pub fn string() *T {
return @as(*const fn (*c.objc_class, *c.objc_selector) callconv(.C) *T, @ptrCast(&c.objc_msgSend))(T.class(), sel_string);
Expand Down
4 changes: 2 additions & 2 deletions src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ pub const mach = struct {
}
extern "objc" fn objc_alloc_init(class: *anyopaque) *AppDelegate;

pub fn setRunBlock(self: *AppDelegate, block: *anyopaque) void {
pub fn setRunBlock(self: *AppDelegate, block: *foundation.ns.Block(fn () void)) void {
method(self, block);
}
const method = @extern(
*const fn (*AppDelegate, *anyopaque) callconv(.C) void,
*const fn (*AppDelegate, *foundation.ns.Block(fn () void)) callconv(.C) void,
.{ .name = "\x01-[MACHAppDelegate setRunBlock:]" },
);
};
Expand Down
Loading

0 comments on commit c562628

Please sign in to comment.