Created
May 16, 2015 23:54
-
-
Save rraallvv/0db64510a5fbd4f7dfba to your computer and use it in GitHub Desktop.
ObjC wrapper block
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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