6

I have Objective-C class in my iOS project that implements Objective-C and C code in the same class. I changed the extension to .mm and this part goes well. Now I want to set a C method that will call the Objective-C method in the same class. The problem I get is when I am trying to call self from the C method. Here is the code :

void SetNotificationListeners(){
    [self fireSpeechRecognition];
}

the error is :

Use of undeclared identifier 'self'

how can I manage this?

orthehelper
  • 4,009
  • 10
  • 40
  • 67
  • That's iOS, not IOS. Anyway, why do you expect `self` to be accessible from within a function that does **not** belong to the class? That just doesn't make sense. You'll need to pass in the instance (object) itself as an argument. –  Nov 24 '13 at 09:39
  • 2
    Why have you changed the extension to `.mm` when you are using Objective-C and C (you don't mention C++)? – trojanfoe Nov 24 '13 at 09:40

4 Answers4

12

You have to pass the instance pointer to the C function:

void SetNotificationListeners(void *uData)
{
    MyClass *obj = (__bridge MyClass *)(uData);
    [obj fireSpeechRecognition];
}

- (void)myMethod
{
    // Call C function from Objective-C method:
    myFunction((__bridge void *)(self));
}

(The "brigde" stuff is needed only if you compile with ARC.)

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • Reading this post i ask, where in C you call Objective C ? Here you said "Call C function FROM Objective-C"... doesnt understand ...this make me confusion! rs – Daniel Arantes Loverde Dec 18 '14 at 15:16
3

Either give self as an argument to the function call:

void SetNotificationListeners(void *myObj){
[(MyClass*)myObj fireSpeechRecognition];
}

//in objC
SetNotificationListeners(self);

or have a global variable that holds reference

//global variable
static MyClass *myObj;

//in obj c
myObj = self;
SetNotificationListeners(); //use myObj instead of self in function

The first is better in my opinion.

Mario
  • 4,530
  • 1
  • 21
  • 32
  • 3
    The second is madness :) – zoul Nov 24 '13 at 09:45
  • As I said Id prefer the first option. Funny how I get down voted when the marked answer with 10 up votes in the now found duplicate of this question just mentions the same "madness".... – Mario Nov 24 '13 at 15:27
2

You don’t have to change the file extension. Objective-C is a superset of C, which means you can use plain C in your Objective-C files as you please.

When you write an implementation of an Objective-C method, that method always executes in context of some particular instance, that’s the self part. You get the self in an Objective-C method automagically, but behind the scenes it’s just passed as an argument to the method, see obc_msgsend.

Your plain C function is not a part of the class (plain C functions never are), therefore there’s no instance associated with it when you call it, there’s no implicit self. If you want the function to call some instance, you have to pass the pointer to that instance explicitly. For example some of the plain C APIs have a “context” pointer you can pass when registering for a callback. See the neighboring answers for examples of this.

zoul
  • 102,279
  • 44
  • 260
  • 354
1

In Objective-C methods there are two parameters that are implicitly passed into each method, which are self and _cmd. This is why you can access self from within a method.

You could just pass self as an argument to your c function when calling from an Objective-C method, but with that trivial example I'm not sure why you wouldn't just use a method.

You do not need to change the file extension to .mm unless you are using Objective-C++

Paul.s
  • 38,494
  • 5
  • 70
  • 88