I have to provide a C-style callback for a specific C library in an iOS app. The callback has no void *userData
or something similar. So I am not able to loop in a context. I'd like to avoid introducing a global context to solve this. An ideal solution would be an Objective-C block.
My question: Is there a way to 'cast' a block into a function pointer or to wrap/cloak it somehow?
If your block needs context information, and the callback does not offer any context, I'm afraid the answer is a clear no. Blocks have to store context information somewhere, so you will never be able to cast such a block into a no-arguments function pointer.
A carefully designed global variable approach is probably the best solution in this case.
I know this has been solved but, for interested parties, I have another solution.
Remap the entire function to a new address space. The new resulting address can be used as a key to the required data.
Remember to handle pages that aren't required anymore and note that it takes a lot more memory per invocation than MABlockClosure.
(Tested on iOS)
Technically, you could get access to a function pointer for the block. But it's totally unsafe to do so, so I certainly don't recommend it. To see how, consider the following example:
Running that yields:
Which is what we'd expect from purely executing those blocks directly with
block()
. So, you could useinvoke
as your function pointer.But as I say, this is totally unsafe. Don't actually use this!
If you want to see a write-up of a way to do what you're asking, then check this out: http://www.mikeash.com/pyblog/friday-qa-2010-02-12-trampolining-blocks-with-mutable-code.html
It's just a great write-up of what you would need to do to get this to work. Sadly, it's never going to work on iOS though (since you need to mark a page as executable which you're not allowed to do within your app's sandbox). But nevertheless, a great article.
MABlockClosure can do exactly this. But it may be overkill for whatever you need.