Skip to content

Instantly share code, notes, and snippets.

@rraallvv
Created May 16, 2015 23:54
Show Gist options
  • Save rraallvv/0db64510a5fbd4f7dfba to your computer and use it in GitHub Desktop.
Save rraallvv/0db64510a5fbd4f7dfba to your computer and use it in GitHub Desktop.
ObjC wrapper block
#import <Foundation/Foundation.h>
#import <objc/message.h>
struct BlockDescriptor {
unsigned long reserved;
unsigned long size;
void *rest[1];
};
struct Block {
void *isa;
int flags;
int reserved;
void *invoke;
struct BlockDescriptor *descriptor;
};
enum {
BLOCK_HAS_COPY_DISPOSE = (1 << 25),
BLOCK_HAS_CTOR = (1 << 26), // helpers have C++ code
BLOCK_IS_GLOBAL = (1 << 28),
BLOCK_HAS_STRET = (1 << 29), // IFF BLOCK_HAS_SIGNATURE
BLOCK_HAS_SIGNATURE = (1 << 30),
};
static char *BlockSig(id blockObj) {
struct Block *block = (__bridge void *)blockObj;
struct BlockDescriptor *descriptor = block->descriptor;
assert(block->flags & BLOCK_HAS_SIGNATURE);
int index = 0;
if(block->flags & BLOCK_HAS_COPY_DISPOSE)
index += 2;
return descriptor->rest[index];
}
@interface MAFakeBlock : NSObject {
int _reserved;
IMP _invoke;
struct BlockDescriptor *_descriptor;
const char *_types;
NSMethodSignature *_signature;
}
- (id)initWithTypes:(const char *)types;
@end
@implementation MAFakeBlock
- (id)initWithTypes: (const char *)types {
if((self = [super init])) {
_types = types;
_signature = [NSMethodSignature signatureWithObjCTypes: _types];
_descriptor = malloc(sizeof(struct BlockDescriptor));
_descriptor->size = class_getInstanceSize([self class]);
_descriptor->rest[0] = (void *) _types;
_invoke = [self methodForSelector: NSSelectorFromString(@"")];
}
return self;
}
- (void)dealloc {
free(_descriptor);
}
- (NSMethodSignature *)methodSignatureForSelector: (SEL)sel {
return _signature;
}
- (void)forwardInvocation: (NSInvocation *)inv {
NSUInteger argsCount = [_signature numberOfArguments];
for (NSUInteger i=0; i<argsCount; ++i) {
printf("%s", [_signature getArgumentTypeAtIndex:i]);
}
printf("\n");
}
- (id)copyWithZone: (NSZone *)zone {
return self;
}
@end
int main(int argc, char **argv) {
@autoreleasepool {
id block = ^(NSString *line, BOOL *stop) {
NSLog(@"%@", line);
};
id intblock = [[MAFakeBlock alloc] initWithTypes:BlockSig(block)];
NSString *string = @"line1\nline2\nline3";
[string enumerateLinesUsingBlock:intblock];
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment