如何从C方法调用Objective-C " self " [duplicate]

时间:2023-01-15 14:16:08

This question already has an answer here:

这个问题已经有了答案:

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 :

我的iOS项目中有一个Objective-C类,它在同一个类中实现Objective-C和C代码。我把分机改成了。mm,这部分没问题。现在我想设置一个C方法,它会在同一个类中调用Objective-C方法。我遇到的问题是当我试图从C方法调用self时。这里是代码:

void SetNotificationListeners(){
    [self fireSpeechRecognition];
}

the error is :

错误的是:

Use of undeclared identifier 'self'

how can I manage this?

我该怎么做呢?

4 个解决方案

#1


10  

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

您必须将实例指针传递给C函数:

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.)

(只有使用ARC编译时才需要“brigde”内容。)

#2


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.

您不需要更改文件扩展名。Objective-C是C的超集,这意味着您可以在Objective-C文件中使用简单的C。

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.

当您编写一个Objective-C方法的实现时,该方法总是在某个特定实例的上下文中执行,这就是self部分。你可以在Objective-C方法中自动获得self,但是在幕后它只是作为一个参数传递给这个方法,请参见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.

普通C函数不是类的一部分(普通C函数从来都不是),因此在调用它时没有实例关联,没有隐式self。如果希望函数调用某个实例,则必须显式地将指针传递到该实例。例如,一些普通的C api有一个“上下文”指针,您可以在注册回调时传递它。请参见邻近的答案以获得相关示例。

#3


1  

Either give self as an argument to the function call:

要么将self作为函数调用的参数:

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.

我认为第一个更好。

#4


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.

在Objective-C方法中,有两个参数隐式地传递给每个方法,即self和_cmd。这就是为什么您可以从一个方法中访问self。

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.

当调用Objective-C方法时,你可以将self作为参数传递给你的c函数,但是有了这个小例子,我不确定你为什么不只是使用一个方法。

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

除非使用objective - c++,否则不需要将文件扩展名更改为.mm

#1


10  

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

您必须将实例指针传递给C函数:

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.)

(只有使用ARC编译时才需要“brigde”内容。)

#2


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.

您不需要更改文件扩展名。Objective-C是C的超集,这意味着您可以在Objective-C文件中使用简单的C。

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.

当您编写一个Objective-C方法的实现时,该方法总是在某个特定实例的上下文中执行,这就是self部分。你可以在Objective-C方法中自动获得self,但是在幕后它只是作为一个参数传递给这个方法,请参见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.

普通C函数不是类的一部分(普通C函数从来都不是),因此在调用它时没有实例关联,没有隐式self。如果希望函数调用某个实例,则必须显式地将指针传递到该实例。例如,一些普通的C api有一个“上下文”指针,您可以在注册回调时传递它。请参见邻近的答案以获得相关示例。

#3


1  

Either give self as an argument to the function call:

要么将self作为函数调用的参数:

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.

我认为第一个更好。

#4


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.

在Objective-C方法中,有两个参数隐式地传递给每个方法,即self和_cmd。这就是为什么您可以从一个方法中访问self。

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.

当调用Objective-C方法时,你可以将self作为参数传递给你的c函数,但是有了这个小例子,我不确定你为什么不只是使用一个方法。

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

除非使用objective - c++,否则不需要将文件扩展名更改为.mm