I'm doing some Interop from Mono C# to Obj-C and ran into this problem. The C# code needs to pass a callback - which it does with a function pointer. I can get the function pointer from the Obj-C side and call it and everything works. But I now need to give that function pointer as a callback to third party API which works with blocks as a callback. I want the third party to call the C# function - so in a way i'm trying to either convert the function pointer to a block so the third party can run it, or make some sort of a bridge - create my own block that runs that function pointer and give it to the third party. I can't seem to find a way to do that - how would I generate a block with info of which function to run and then give it to the third party. Maybe there's another option for me?
Edit: Putting the function in a global variable might work but I want to be able to have a multitude of those as the third party API is asynchronous and I don't want it calling the wrong callback.
Code I tried :
typedef void (*DummyAction)(char * result);
typedef void (^DummyBlock)(char * result);
@interface FunctionToBlock : NSObject
{
DummyAction function;
DummyBlock block;
}
- (id) initWithFunction: (DummyAction) func;
- (DummyBlock) block;
@end
@implementation FunctionToBlock : NSObject
- (id) initWithFunction: (DummyAction) func {
if (self = [super init]) {
function = func;
block = ^(char * result) {
function(result);
};
}
return self;
}
- (DummyBlock) block {
return block;
}
@end
And then I run this with
void RegisterCallback( char * text, DummyAction callback)
{
FunctionToBlock *funcToBlock = [[FunctionToBlock alloc] initWithFunction : callback];
funcToBlock.block(text);
}
And it fails with BAD_ACCESS. Maybe i'm doing something wrong as i'm not very proficient with Obj-C yet. I can confirm that the callback is ok if run directly and that the block is being called but it fails on the function(result) line.
What about
void (*myFunc)(int x); // ... your function pointer
void (^myBlock)(int) = ^(int x) {
myFunc(x);
};
Then myBlock
is a block that captures the value of the function pointer and calls the function when the block is executed.
ADDED: My suggestion, based on your code, using a @property (and assuming that you compile with ARC):
FunctionToBlock.h:
typedef void (*DummyAction)(char * result);
typedef void (^DummyBlock)(char * result);
@interface FunctionToBlock : NSObject
{
DummyAction function; // Not really needed.
}
- (id) initWithFunction: (DummyAction) func;
@property(copy, nonatomic) DummyBlock block; // "copy" is important here!
@end
FunctionToBlock.m:
#import "FunctionToBlock.h"
@implementation FunctionToBlock : NSObject
@synthesize block = _block; // Can be ommitted if you use Xcode 4.4 or later.
- (id) initWithFunction: (DummyAction) func
{
if (self = [super init]) {
function = func; // Not really needed.
self.block = ^(char * result) {
func(result); // Use "func", not "self->function", to avoid retain cycle.
};
}
return self;
}
why not just have a simple function
typedef void (*DummyAction)(char * result);
typedef void (^DummyBlock)(char * result);
DummyBlock functionToBlock(DummyAction func) {
return [[^(char * result) {
func(result);
} copy] autorelease];
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With