Подтвердить что ты не робот

Как вызвать метод Objective-C из метода C?

У меня есть объект Obj-C с кучей методов внутри него. Иногда метод должен вызывать другой метод внутри одного и того же объекта. Я не могу понять, как получить метод C для вызова метода Obj-C...

РАБОТЫ: Метод Obj-C, вызывающий метод Obj-C:

[self objCMethod];

РАБОТЫ: Метод Obj-C, вызывающий метод C:

cMethod();

НЕ РАБОТАЕТ: Метод C, вызывающий метод Obj-C:

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

В последнем примере компилятор выплевывает эту ошибку:

ошибка: "self" uneclared (сначала использовать в этой функции)

Два вопроса. Почему функция C не видит переменную "self" , даже если она находится внутри объекта "self" , и как я могу ее вызвать, не вызывая ошибки? Большое спасибо за любую помощь!:)

4b9b3361

Ответ 1

Чтобы это сработало, вы должны определить метод C следующим образом:

void cMethod(id param);

и когда вы его вызываете, назовите его так:

cMethod(self);

тогда вы сможете написать:

[param objcMethod];

В cMethod.

Это связано с тем, что переменная self является специальным параметром, который автоматически передается методам Objective-C. Поскольку методы C не пользуются этой привилегией, если вы хотите использовать self, вам необходимо отправить его самостоятельно.

Подробнее в разделе "Реализация метода" руководства по программированию.

Ответ 2

Я знаю, что на ваш вопрос уже ответил Aviad, но просто чтобы добавить к информации, так как это не связано:

В моем случае мне нужно было вызвать метод Objective-C из функции C, которую я сам не вызывал (функция события Carbon, вызванная регистрацией глобального события hotkey), поэтому передача self в качестве параметра была невозможна. В этом конкретном случае вы можете сделать это:

Определите переменную класса в вашей реализации:

id thisClass;

Затем в вашем методе init установите его в self:

thisClass = self;

Затем вы можете вызвать методы Objective-C из любой функции C в классе без необходимости передавать self в качестве параметра функции:

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

Ответ 3

Функция C не является "внутри объекта self". На самом деле ничего нет.

Objective-C методы эффективно получают self как неявный аргумент, с магией, выполняемой под капотом. Для простых функций C они не связаны ни с каким классом или объектом, и там нет магии вызова, поэтому нет self. Если вам это нужно, вам нужно передать его в свою C-функцию явно как аргумент.

Ответ 4

Чтобы быть полностью правдивым, нет такой вещи, как метод С. C имеет функции. Чтобы проиллюстрировать разницу, посмотрите на следующие примеры:

Это рабочая программа на 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;
}

Вот реализация этой программы 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;
}

Вывод чистой программы C:

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

Вывод программы 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

Единственное отличие - это все нежелательные файлы, которые NSLog помещает перед текстом. Функциональность точно такая же. Итак, в C вы можете использовать что-то вроде подобных методов, но они действительно просто функции, которые включают указатель на структуру.

Я не думаю, что это ответило на ваш первоначальный вопрос, но он прояснил некоторые терминологические проблемы, которые, по-видимому, возникли.

Ответ 5

Еще один вариант ответов, предоставленных до сих пор, заключается в использовании функции objc_msgSend(), обеспечиваемой средой Objective-C.