• Stars
    star
    359
  • Rank 118,537 (Top 3 %)
  • Language
    Objective-C
  • License
    Other
  • Created about 14 years ago
  • Updated about 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

ObjC block -> C function pointer using libffi

MABlockClosure

MABlockClosure uses libffi to generate function pointers wrapping Objective-C blocks. It will generate a function pointer with the same parameter and return types, which when invoked, invokes the block. Mac OS X is fully supported, and there is also experimental support for iOS.

MABlockClosure is released under a BSD license. For the official license, see the LICENSE file.

Quick Start

The easiest way to use the code is with the BlockFptr convenience function. This function returns a function pointer whose lifetime is equivalent to that of the block passed to it. Note that the block must be on the heap or global: stack blocks will not correctly destroy the function pointer when they go out of scope.

Example with a callback:

atexit(BlockFptr(^{ ...do something, no captured variables so it's a global block... }));

Use a block to add a new method to NSObject:

int captured = 42;
id block = ^(id self, SEL _cmd) { NSLog(@"captured is %d", captured); };
block = [block copy];
class_addMethod([NSObject class], @selector(my_printCaptured), BlockFptr(block));

For more control over the lifetime of the returned function pointer, you can use the MABlockClosure class. When an MABlockClosure object is destroyed, the function pointer it gives you from the -fptr method is also destroyed.

Compatibility

Because MABlockClosure uses libffi to do all of the heavy lifting, it should work on any processor architecture where libffi is available.

The interface between blocks and libffi depends on block signature metadata being present. This metadata is generated when building with the build of clang that ships with the latest Xcode. It is not generated when building with the currently shipping gcc as of this writing. The code will fail quickly and loudly if it is not present.

The block signature metadata is the same format as Objective-C method signature strings. Parsing these strings is tricky. The code will parse every primitive type supported by the @encode syntax as well as NSRect, NSPoint, NSSize, and their CG equivalents. Other structs can be added relatively easily, but it is a manual process as the code makes no attempt to actually parse structs.

Standard libffi closures require calling mprotect to mark data pages as executable. This is not currently supported on iOS, so they don't work there. There is an experimental libffi modification to make this work, made by Landon Fuller. More on this below.

iOS Support

Due to iOS not supporting the creation of executable data, standard libffi closures don't work there. Landon Fuller has developed a fork of libffi that uses some crazy dirty tricks to work around this, and MABlockClosure works with this fork. This requires building a custom libffi, but iOS doesn't even offer libffi anyway, so this would be required either way.

Note that libffi closures on iOS are highly experimental and you should tread with caution. They have worked well in limited testing so far, but be prepared for trouble.

This libffi fork is located here:

http://github.com/landonf/libffi-ios

Here are some brief instructions for how to get this fork up and running with MABlockClosure.

First, check out the libffi-ios repository next to your project's folder:

git clone http://github.com/landonf/libffi-ios.git

Next, use the build-ios.sh script to configure and build it using the proper flags. (Note that you may need to edit the SDK setting in this script first.)

cd libffi-ios
./build-ios.sh

Now everything should be built. Then you need to tell your Xcode project where to find this stuff.

You need to make two changes to your project's build settings.

First, add the following to Other Linker Flags:

../libffi-ios/build-ios/.libs/libffi.a

Next, add the following to Header Search Paths:

../libffi-ios/build-ios/include

Finally, add the MABlockClosure files to your project. You should now be able to use MABlockClosure on iOS.

More Repositories

1

MAObjCRuntime

ObjC wrapper for ObjC runtime API
Objective-C
1,534
star
2

MAKVONotificationCenter

Better key-value observing for Cocoa
Objective-C
528
star
3

MAZeroingWeakRef

Zeroing weak references for retain/release Objective-C
Objective-C
361
star
4

Circle

Objective-C
313
star
5

MACollectionUtilities

Smalltalk-inspired collection utility methods and macros for Cocoa
Objective-C
250
star
6

BinaryCoder

An example implementation of Swift.Codable using a simple binary format
Swift
168
star
7

memorydumper2

Swift
161
star
8

SwiftObserverSet

NSNotificationCenter re-conceptualization for Swift
Swift
132
star
9

MADispatchQueue

A spiritual reimplementation of the basics of dispatch_queue, for educational purposes
Objective-C
128
star
10

memorydumper

Swift
106
star
11

MAMirroredQueue

Objective-C
98
star
12

MAFuture

Proxying futures library for Objective-C
Objective-C
89
star
13

MAAsyncIO

GCD-based async IO
Objective-C
83
star
14

MAObject

Reimplementation of most NSObject functionality, for educational purposes
Objective-C
83
star
15

TSUD

Type-Safe User Defaults - Swifty NSUserDefaults wrapper
Swift
77
star
16

MABGTimer

Background timers, not associated with any thread, for Objective-C
Objective-C
71
star
17

iphone-user-performance-tests

A utility for doing simple tests of an iOS device's user-facing performance, and some collected results.
Swift
51
star
18

MAGenerator

Blocks/macros-based library for building Python-like generators in Objective-C
Objective-C
48
star
19

MABlockForwarding

Generic block forwarding, like forwardInvocation:
Objective-C
47
star
20

mikeash.com-svn

Legacy repository converted over from mikeash.com/svn/
Objective-C
43
star
21

PerformanceTest

Simple performance testing for various common operations in Mac/iOS programs
Objective-C++
40
star
22

DemoXcodePlugin

Objective-C
40
star
23

NSRectangle

Objective-C
39
star
24

XCommentWrap

Xcode extension for hard wrapping comments.
Swift
38
star
25

MANotificationCenter

NSNotificationCenter workalike, for education purposes
Objective-C
36
star
26

ChemicalBurn

Objective-C
35
star
27

MAInvocation

Reimplementation of NSInvocation, minus floating-point support, for educational purposes
Objective-C
35
star
28

MACollections

Reimplementation of some Cocoa collections, for educational purposes
Objective-C
35
star
29

GPULife

GPU-accelerated Game of Life screensaver
Objective-C
30
star
30

MAPlistTypeChecking

Conveniences for type-checking and reporting errors in plists, JSON, and other similar structures
Objective-C
26
star
31

MAAutoreleasePool

NSAutoreleasePool workalike for educational purposes
Objective-C
23
star
32

MASON

Friendly JSON decoding API for Swift
Swift
20
star
33

StringWithFormat

Reimplementation of stringWithFormat: for educational purposes
Objective-C
18
star
34

MADispatchGroup

Reimplementation of dispatch_group, for educational purposes.
Objective-C
12
star
35

MAParanoidAllocator

Objective-C
12
star
36

refcounting

Implementation of ObjC refcounting, for educational purposes
Objective-C
10
star
37

Smurf

A Swift library which renames Any to Smurf
Swift
9
star
38

sitescan

Python
5
star
39

Turmites

My Turmites screensaver, from the distant past
Objective-C
5
star
40

compressor

Simple Arduino audio compressor code
Arduino
4
star
41

creatures

My extremely, extremely old artificial life program
Objective-C
4
star
42

Centrifugal

Objective-C
2
star
43

BlockContextExecution

BlockContextExecution
Objective-C
2
star
44

pyunitcalc

Python
1
star