Function Pointers in Objective C

Function Pointers in Objective C

Typically, you need two pieces of information to call back into Objective-C; the method to be invoked and the object to invoke it upon. Neither just a selector or just the IMP -- the instanceMethodForSelector: result -- will be enough information.

Most callback APIs provide a context pointer that is treated as an opaque value that is passed through to the callback. This is the key to your conundrum.

I.e. if you have a callback function that is declared as:

typedef void (*CallBackFuncType)(int something, char *else, void *context);

And some API that consumes a pointer of said callback function type:

void APIThatWillCallBack(int f1, int f2, CallBackFuncType callback, void *context);

Then you would implement your callback something like this:

void MyCallbackDude(int a, char *b, void *context) {
[((MyCallbackObjectClass*)context) myMethodThatTakesSomething: a else: b];
}

And then you would call the API something akin to this:

MyCallbackObjectClass *callbackContext = [MyCallbackObjectClass new];
APIThatWillCallBack(17, 42, MyCallbackDude, (void*)callbackContext);

If you need to switch between different selectors, I would recommend creating a little glue class that sits between the callback and the Objective-C API. The instance of the glue class could contain the configuration necessary or logic necessary to switch between selectors based on the incoming callback data.

Function pointers in Objective C

Here pNewMsgeFunc is the alias name of the function pointer tNewMsg which is created inside the structure stRsStruct

No, it's not. tNewMsg is a name that identifies a type.

typedef RsMsg* (*tNewMsg)(void);

...but pNewMessageFunc is an object of that type.

Look at it this way. In this code:

typedef unsigned int uint;
uint n = 42;

n is not an alias of uint. Rather, n is a variable of type uint.

So, pNewMessageFunc is a global variable (of type pointer-to-function-which-takes-no-parameters-and-returns-pointer-to-RsMsg) which you never initialize.

Modifying a function pointer passed to a method?

This can be done using pointers to function pointers. Perhaps the most readable way to do it is to typedef your function pointer, like this:

typedef void (*FunPtr)(int a, float b);

Then use a pointer of that typedef-ed type to assign in a function, like this:

void foo(int a, float b) {
printf("FOO : %d %f\n", a, b);
}

void bar(int a, float b) {
printf("BAR : %d %f\n", a, b);
}

// This function receives a pointer to function pointer
void assign(int n, FunPtr *ptr) {
if (n == 0) {
*ptr = foo;
} else {
*ptr = bar;
}
}

Here is how you call assign from your code:

int main(void) {
FunPtr f;
assign(0, &f);
f(10, 20.5);
assign(1, &f);
f(10, 20.5);
return 0;
}

Demo.

Note: You are right about blocks in Objective-C greatly reducing the need for direct use of function pointers. However, you can use a similar typedef trick with pointers to blocks.

Calling an objective c method using a function pointer from a c++ method

The problem is that the function signature of Objective-C methods is not as simple as you might think.

In order to make object-oriented programming possible, Objective-C methods take two implicit arguments: id self, SEL _cmd, the calling object and the selector sent - these need to be passed. You will need to get an object to call the method on, and you should store the selector too. Then, change your function type definition to the correct one:

typedef void (*FuncPtr) (id, SEL, status);

To be read: [1], [2] (near the part typedef id (*IMP)(id, SEL, ...))

Converting a function pointer to a block in objective-C

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];
}

Globally declaring a function pointer in Objective C

The name is in the wrong place:

@interface GetStatusUpdate : NSObject 
{
void (^completionHandler)(UIBackgroundFetchResult);
}

Then, some where, you have to define the block:

completionHandler = ^(UIBackgroundFetchResult result) {
// do your work
};

or assign it as you did.

I find this helpful when I have to work with blocks: http://fuckingblocksyntax.com/

As an aside, your block is being stored as an instance variable, not a global variable.

Objective-c function pointer

If you know the method in advance:

[self performSelector:@selector(myMethod) withObject:nil];

If you don't know the method name in advance:

SEL selector = NSSelectorFromString(someSelectorStringYoureGiven);
[self performSelector:selector withObject:nil];

Both these examples assume your function accepts no arguments, nor requires execution on a different thread, nor requires delayed execution. There are many variants for all combinations of those conditions (and NSInvocation for even more complex cases). Search performSelector in xcode's documentation to see all the variants.

Function pointer to objc class member method, for use in C++?

"Function pointer" is not possible here, because you can't use a function pointer to call an instance method (unless you pass around the instance with the function pointer).

You can create a callable object, however.

struct Callback {
MyViewControllerClass *instance;
void operator()() {
[instance objcCallback];
}
};

You could also use a C++ lambda, which is vaguely equivalent.



Related Topics



Leave a reply



Submit