Can a C function be used as a selector in Cocoa? Can a C function be used as a selector in Cocoa? multithreading multithreading

Can a C function be used as a selector in Cocoa?


Roll your own:

// In some .h file.  #import to make the extension methods 'visible' to your code.@interface NSThread (FunctionExtension)+(void)detachNewThreadByCallingFunction:(void (*)(void *))function data:(void *)data;-(id)initWithFunction:(void (*)(void *))function data:(void *)data;@end// In some .m file.@implementation NSThread (FunctionExtension)+(void)startBackgroundThreadUsingFunction:(id)object{  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];  void (*startThreadFunction)(void *) = (void (*)(void *))[[object objectForKey:@"function"] pointerValue];  void *startThreadData               = (void *)          [[object objectForKey:@"data"] pointerValue];  if(startThreadFunction != NULL) { startThreadFunction(startThreadData); }  [pool release];  pool = NULL;}+(void)detachNewThreadByCallingFunction:(void (*)(void *))function data:(void *)data{  [[[[NSThread alloc] initWithFunction:function data:data] autorelease] start];}-(id)initWithFunction:(void (*)(void *))function data:(void *)data{  return([self initWithTarget:[NSThread class] selector:@selector(startBackgroundThreadUsingFunction:) object:[NSDictionary dictionaryWithObjectsAndKeys:[NSValue valueWithPointer:function], @"function", [NSValue valueWithPointer:data], @"data", NULL]]);}@end

NOTE: I wrote the above code and here by place it in the public domain. (sometimes the lawyers like this kind of stuff) It is also completely untested!

You can always remove the NSAutoreleasePool bits if you can guarantee that the thread entry function also creates one... but it's harmless, has no speed penalty what-so-ever, and makes calling arbitrary C functions that much more simpler. I'd say just keep it there.

And you can use it like so:

void bgThreadFunction(void *data){  NSLog(@"bgThreadFunction STARTING!! Data: %p", data);}-(void)someMethod{  // init and then start later...  NSThread *bgThread = [[[NSThread alloc] initWithFunction:bgThreadFunction data:(void *)0xdeadbeef] autorelease];  // ... assume other code/stuff here.  [bgThread start];  // Or, use the all in one convenience method.  [NSThread detachNewThreadByCallingFunction:bgThreadFunction data:(void *)0xcafebabe];}

When run:

2009-08-30 22:21:12.529 test[64146:1303] bgThreadFunction STARTING!! Data: 0xdeadbeef2009-08-30 22:21:12.529 test[64146:2903] bgThreadFunction STARTING!! Data: 0xcafebabe


Create an Objective-C class with a method that simply calls that function. Take the selector of that method and pass it to NSThread API.


Well, I'm not sure if it's possible, but keep in mind that every Objective-C method has two implicit/hidden arguments, self and _cmd. An IMP is usually typedef'd like this:

typedef id (*IMP)(id,SEL,...);

If you want to jerry-rig methods and selectors, you need to have a method that looks like that:

void func (id self, SEL _cmd, void *firstParameter);

But even after that, you need to register a selector name with the runtime, then you need to associate that selector with the method, but this is done on a class-by-class basis (i.e. classes can have different implementations of the same selector name), so you at least need to have a dummy class.

It is much, much simpler just to create a dummy class and dummy instance of that class than call the various runtime API just to get NSThread to invoke a single C function.