views:

3291

answers:

4

I am writing an Objective-C class but is uses an API written in C. This is mostly fine as mixing C calls with Objective-C calls causes few problems.

However one of the API call requires a call back method (example):

success = CFHostSetClient(host, MyCFHostClientCallBack, &context);

Where MyCFHostClientCallBack is a C function defined like this:

static void MyCFHostClientCallBack(CFHostRef host, CFHostInfoType typeInfo, const CFStreamError *error, void *info);
  1. Can/How do I call an Objective-C method in place of this?
  2. Can/Should I mix C function in with my Objective-C call?
  3. How do I mix C function with Objective-C methods?
+2  A: 

What I've always found helpful in this situation is to make an Obj-C wrapper on top of the C API. Implement what you need to using C functions, and build an Objective-C class (or two) on top of it, so that's all the outside world will see. For example, in the case of a callback like this, you might make a C function that calls Obj-C delegate methods on other objects.

Marc Charbonneau
+4  A: 

To call Objective-C code from a C callback I would use something like:

void * refToSelf;
int cCallback()
{
    [refToSelf someMethod:someArg];
}

@implementation SomeClass
- (id) init
{
     self = [super init];
     refToSelf = self;
}
- (void) someMethod:(int) someArg
{
}
diciu
Just one addition: many callbacks allow to specify "user data"; in this case, the object pointer could be used as the user data (and you don't need to global variable refToSelf anymore). It might be that your callback function supports "user data" in the info pointer.
ashcatch
+5  A: 

Mixing C and Objective-C methods and function is possible, here is a simple example that uses the SQLite API within an iPhone App: (course site)

http://www.stanford.edu/class/cs193p/downloads/09-MySQLiteTableView.zip

C functions need to be declared outside of the @implementation in an Objective-C (.m) file.

int MyCFunction(int num, void *data)
{
     //code here...
}

@implementation

- (void)MyObjectiveCMethod:(int)number withData:(NSData *)data
{
      //code here
}

@end

Because the C function is outside of the @implementation it cannot call methods like

[self doSomething]

and has no access to ivars.

This can be worked around as long as the call-back function takes a userInfo or context type parameter, normally of type void*. This can be used to send any Objective-C object to the C function.

As in the example, this can be manipulated with normal Objective-C operations.

In addition please read this answer: http://stackoverflow.com/questions/801976/mixing-c-functions-in-an-objective-c-class/802059#802059

rjstelling
+1  A: 

Can/How do I call an Objective-C method in place of this?

You cannot.

Can/Should I mix C function in with my Objective-C call?

Yes. Write a C function and use that as the callback to the CF function.

How do I mix C function with Objective-C methods?

You can set self as the info pointer in your context structure. That will be passed to the callback. Then, in the callback, cast the info pointer back to id:

MyClass *self = (id)info;

You can then send self messages. You still can't directly access instance variables, though, since a C function is outside of the @implementation section. You'll have to make them properties. You can do this with a class extension. (Contrary to what that document says, you would not declare the extension inside @implementation, but in the same file with it, generally right above it.)

Peter Hosey