views:

312

answers:

2

I am mixing Objective-C parts into a C++ project (please don't argue about that, its cross-platform).
I now want to invoke some C++ functions or methods on the correct thread (i.e. the main thread) in a cocoa enviroment.

My current approach is passing function pointers to an objective-c instance (derived from NSObject) and do performSelector/performSelectorOnMainThread on it.
But the performSelectors expect objects as their arguments, so how would one usually wrap this?

Example:

 typedef void(*FnPtr)(void*);
 FnPtr fn;
 [someInstance performSelector:@selector(test:) withObject:fn];

... where test is declared as:

- (void)test:(FnPtr)fn;

Have to add that i only started with objective-c this week, so if there is a better way i'd be also glad to hear about it.
Also note that i don't have any access to the main loop or any application objects because the project is an browser plug-in (currently only targetting Safari on the mac).

+1  A: 

As answered by smorgan here, NSValue is designed as a container for scalar C & Objective-C types:

- (void)test:(NSValue*)nv
{
    FnPtr fn = [nv pointerValue];
    // ...
}

// usage:
NSValue* nv = [NSValue valueWithPointer:fn];
[someInstance performSelector:@selector(test:) withObject:nv];
Georg Fritzsche
A: 

I am not sure if my solution is considered sane / correct -- I do however frequently pass pointers by simply typecasting them to (id)s. That is dirty but does work for me. The possibly cleaner way would be using NSValue.

Till
I don't know whats supposed to happen if the selector isn't actually called, e.g. when its module is unloaded. If the implementor of `performSelector` is supposed to clean up the object wouldn't that result in undefined behaviour?
Georg Fritzsche
-performSelector:withObject:afterDelay: and a few others actually try to retain the parameter and target. You really don't want to pass a non-object type there.
uliwitness