如何从C方法调用Objective-C方法?

时间:2023-01-15 14:20:45

I have an Obj-C object with a bunch of methods inside of it. Sometimes a method needs to call another method inside the same object. I can't seem to figure out how to get a C method to call a Obj-C method...

我有一个object - c对象,里面有很多方法。有时一个方法需要调用同一个对象中的另一个方法。我似乎想不出如何让C方法调用object -C方法……

WORKS: Obj-C method calling an Obj-C method:

工作:object - c方法调用object - c方法:

[self objCMethod];

WORKS: Obj-C method calling a C method:

工作:object -C方法调用C方法:

cMethod();

DOESN'T WORK: C method calling an Obj-C method:

无效:C方法调用object -C方法:

[self objCMethod];     // <--- this does not work

The last example causes the compiler spits out this error:

最后一个例子导致编译器输出这个错误:

error: 'self' undeclared (first use in this function)

错误:“self”未声明(在此函数中首次使用)

Two questions. Why can't the C function see the "self" variable even though it's inside of the "self" object, and how do I call it without causing the error? Much thanks for any help! :)

两个问题。为什么C函数不能看到“self”变量,即使它在“self”对象中,我如何调用它而不产生错误?非常感谢您的帮助!:)

5 个解决方案

#1


47  

In order for that to work, you should define the C method like this:

为了实现这一点,您应该像这样定义C方法:

void cMethod(id param);

and when you call it, call it like this:

当你这样称呼它时

cMethod(self);

then, you would be able to write:

然后,你就可以写下:

[param objcMethod];

In your cMethod.

在你cMethod。

This is because the self variable is a special parameter passed to Objective-C methods automatically. Since C methods don't enjoy this privilege, if you want to use self you have to send it yourself.

这是因为self变量是自动传递给Objective-C方法的特殊参数。因为C方法不享受这个特权,如果你想使用self,你必须自己发送。

See more in the Method Implementation section of the programming guide.

请参阅编程指南的方法实现部分。

#2


24  

I know your question is already answered by Aviad but just to add to the info since this is not unrelated:

我知道Aviad已经回答了你的问题,但我想补充一下,因为这不是无关的:

In my case I needed to call an Objective-C method from a C function that I did not call myself (a Carbon Event function triggered by registering a global hotkey event) so passing self as a parameter was impossible. In this particular case you can do this:

在我的例子中,我需要调用一个C函数的Objective-C方法,我没有调用自己(通过注册一个全局热键事件触发的碳事件函数),所以将self作为参数是不可能的。在这种情况下,你可以这样做:

Define a class variable in your implementation:

在实现中定义一个类变量:

id thisClass;

Then in your init method, set it to self:

然后在init方法中,将其设置为self:

thisClass = self;

You can then call Objective-C methods from any C function in the class without the need to pass self as a parameter to the function:

然后,您可以从类中的任何C函数调用Objective-C方法,而不需要将self作为参数传递给函数:

void cMethod([some parameters]) {
    [thisClass thisIsAnObjCMethod];
}

#3


10  

C function is not "inside of the self object". In fact, nothing is.

C函数不是“自对象的内部”。事实上,没有什么。

Objective-C methods effectively get self as an implicit argument, with magic done under the hood. For plain C functions, they aren't associated with any class or object, and there's no call magic, so no self. If you need it, you need to pass it to your C function explicitly as an argument.

Objective-C方法有效地将self作为一个隐式的参数,在引擎盖下完成魔法。对于普通的C函数,它们与任何类或对象都没有关联,也没有所谓的魔法,所以没有self。如果需要,需要将它作为参数显式地传递给C函数。

#4


4  

To be totally truthful, there is no such thing as a C method. C has functions. To illustrate the difference, look at the following examples:

说实话,C方法是不存在的。C函数。为了说明差异,请看下面的例子:

This is a working C program that defines a type and two functions that go along with it:

这是一个有效的C程序,它定义了一个类型和两个与它相关的函数:

#include <stdio.h>

typedef struct foo_t {
    int age;
    char *name;
} Foo;

void multiply_age_by_factor(int factor, Foo *f) {
    f->age = f->age * factor;
}

void print_foo_description(Foo f) {
    printf("age: %i, name: %s\n", f.age, f.name);
}

int main() {
    Foo jon;
    jon.age = 17;
    jon.name = "Jon Sterling";

    print_foo_description(jon);
    multiply_age_by_factor(2, &jon);
    print_foo_description(jon);

    return 0;
}

Here is an Objective-C implementation of that program:

这是该项目的Objective-C实现:

#import <Foundation/Foundation.h>

@interface Foo : NSObject {
    NSUInteger age;
    NSString *name;
}

@property (nonatomic, readwrite) NSUInteger age;
@property (nonatomic, copy) NSString *name;

- (void)multiplyAgeByFactor:(NSUInteger)factor;
- (NSString *)description;
- (void)logDescription;

@end


@implementation Foo 
@synthesize age;
@synthesize name;

- (void)multiplyAgeByFactor:(NSUInteger)factor {
    [self setAge:([self age] * factor)];
}

- (NSString *)description {
    return [NSString stringWithFormat:@"age: %i, name: %@\n", [self age], [self name]];
}

- (void)logDescription {
    NSLog(@"%@",[self description]);
}

@end


int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    Foo *jon = [[[Foo alloc] init] autorelease];
    [jon setAge:17];
    [jon setName:@"Jon Sterling"];

    [jon logDescription];
    [jon multiplyAgeByFactor:2];
    [jon logDescription];

    [pool drain];

    return 0;
}

The output of the pure C program was:

纯C程序输出为:

age: 17, name: Jon Sterling
age: 34, name: Jon Sterling

The output of the Objective-C program was:

Objective-C程序输出为:

2009-08-25 17:40:52.818 test[8963:613] age: 17, name: Jon Sterling
2009-08-25 17:40:52.828 test[8963:613] age: 34, name: Jon Sterling

The only difference is all the junk that NSLog puts before the text. The functionality is exactly the same. So, in C, you can use something sort of like methods, but they are really just functions that include a pointer to a struct.

唯一的区别是NSLog把所有垃圾放到文本前面。功能完全相同。所以,在C中,你可以使用一些类似的方法,但它们实际上只是包含指向struct的指针的函数。

I don't think this answered your original question, but it did clear up some terminology issues you appear to have been having.

我不认为这回答了你最初的问题,但它确实澄清了一些术语问题。

#5


2  

Another option to the answers given thus far is to use the objc_msgSend() function provided by the Objective-C runtime.

到目前为止给出的答案的另一个选项是使用Objective-C运行时提供的objc_msgSend()函数。

#1


47  

In order for that to work, you should define the C method like this:

为了实现这一点,您应该像这样定义C方法:

void cMethod(id param);

and when you call it, call it like this:

当你这样称呼它时

cMethod(self);

then, you would be able to write:

然后,你就可以写下:

[param objcMethod];

In your cMethod.

在你cMethod。

This is because the self variable is a special parameter passed to Objective-C methods automatically. Since C methods don't enjoy this privilege, if you want to use self you have to send it yourself.

这是因为self变量是自动传递给Objective-C方法的特殊参数。因为C方法不享受这个特权,如果你想使用self,你必须自己发送。

See more in the Method Implementation section of the programming guide.

请参阅编程指南的方法实现部分。

#2


24  

I know your question is already answered by Aviad but just to add to the info since this is not unrelated:

我知道Aviad已经回答了你的问题,但我想补充一下,因为这不是无关的:

In my case I needed to call an Objective-C method from a C function that I did not call myself (a Carbon Event function triggered by registering a global hotkey event) so passing self as a parameter was impossible. In this particular case you can do this:

在我的例子中,我需要调用一个C函数的Objective-C方法,我没有调用自己(通过注册一个全局热键事件触发的碳事件函数),所以将self作为参数是不可能的。在这种情况下,你可以这样做:

Define a class variable in your implementation:

在实现中定义一个类变量:

id thisClass;

Then in your init method, set it to self:

然后在init方法中,将其设置为self:

thisClass = self;

You can then call Objective-C methods from any C function in the class without the need to pass self as a parameter to the function:

然后,您可以从类中的任何C函数调用Objective-C方法,而不需要将self作为参数传递给函数:

void cMethod([some parameters]) {
    [thisClass thisIsAnObjCMethod];
}

#3


10  

C function is not "inside of the self object". In fact, nothing is.

C函数不是“自对象的内部”。事实上,没有什么。

Objective-C methods effectively get self as an implicit argument, with magic done under the hood. For plain C functions, they aren't associated with any class or object, and there's no call magic, so no self. If you need it, you need to pass it to your C function explicitly as an argument.

Objective-C方法有效地将self作为一个隐式的参数,在引擎盖下完成魔法。对于普通的C函数,它们与任何类或对象都没有关联,也没有所谓的魔法,所以没有self。如果需要,需要将它作为参数显式地传递给C函数。

#4


4  

To be totally truthful, there is no such thing as a C method. C has functions. To illustrate the difference, look at the following examples:

说实话,C方法是不存在的。C函数。为了说明差异,请看下面的例子:

This is a working C program that defines a type and two functions that go along with it:

这是一个有效的C程序,它定义了一个类型和两个与它相关的函数:

#include <stdio.h>

typedef struct foo_t {
    int age;
    char *name;
} Foo;

void multiply_age_by_factor(int factor, Foo *f) {
    f->age = f->age * factor;
}

void print_foo_description(Foo f) {
    printf("age: %i, name: %s\n", f.age, f.name);
}

int main() {
    Foo jon;
    jon.age = 17;
    jon.name = "Jon Sterling";

    print_foo_description(jon);
    multiply_age_by_factor(2, &jon);
    print_foo_description(jon);

    return 0;
}

Here is an Objective-C implementation of that program:

这是该项目的Objective-C实现:

#import <Foundation/Foundation.h>

@interface Foo : NSObject {
    NSUInteger age;
    NSString *name;
}

@property (nonatomic, readwrite) NSUInteger age;
@property (nonatomic, copy) NSString *name;

- (void)multiplyAgeByFactor:(NSUInteger)factor;
- (NSString *)description;
- (void)logDescription;

@end


@implementation Foo 
@synthesize age;
@synthesize name;

- (void)multiplyAgeByFactor:(NSUInteger)factor {
    [self setAge:([self age] * factor)];
}

- (NSString *)description {
    return [NSString stringWithFormat:@"age: %i, name: %@\n", [self age], [self name]];
}

- (void)logDescription {
    NSLog(@"%@",[self description]);
}

@end


int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    Foo *jon = [[[Foo alloc] init] autorelease];
    [jon setAge:17];
    [jon setName:@"Jon Sterling"];

    [jon logDescription];
    [jon multiplyAgeByFactor:2];
    [jon logDescription];

    [pool drain];

    return 0;
}

The output of the pure C program was:

纯C程序输出为:

age: 17, name: Jon Sterling
age: 34, name: Jon Sterling

The output of the Objective-C program was:

Objective-C程序输出为:

2009-08-25 17:40:52.818 test[8963:613] age: 17, name: Jon Sterling
2009-08-25 17:40:52.828 test[8963:613] age: 34, name: Jon Sterling

The only difference is all the junk that NSLog puts before the text. The functionality is exactly the same. So, in C, you can use something sort of like methods, but they are really just functions that include a pointer to a struct.

唯一的区别是NSLog把所有垃圾放到文本前面。功能完全相同。所以,在C中,你可以使用一些类似的方法,但它们实际上只是包含指向struct的指针的函数。

I don't think this answered your original question, but it did clear up some terminology issues you appear to have been having.

我不认为这回答了你最初的问题,但它确实澄清了一些术语问题。

#5


2  

Another option to the answers given thus far is to use the objc_msgSend() function provided by the Objective-C runtime.

到目前为止给出的答案的另一个选项是使用Objective-C运行时提供的objc_msgSend()函数。