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

Передайте объект Objective-C функции как указатель void *

У меня есть функция:

  myFunction (MyProc callback, void * ref)

Эта функция вызывается из класса Objective-C. Функция передается указателем на обратный вызов (функция в классе) и ссылкой. Ссылка необходима, потому что обратный вызов называется статически и поэтому не имеет контекста. Ссылка ref может использоваться для обеспечения контекста обратного вызова.

Я хочу, чтобы передать класс Objective-C в качестве ссылки. Итак, вопрос:

Как мне передать NSObject в void * и как мне сделать void * как NSObject.

Спасибо заранее.

4b9b3361

Ответ 1

Сделайте что-то вроде этого:

void func(void *q)
{
    NSObject* o = CFBridgingRelease(q);
    NSLog(@"%@", o);
}

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        NSObject* o = [NSObject new];
        func((void*)CFBridgingRetain(o));
    }
    return 0;
}

Обратите внимание, что CFBridgingRetain() и CFBridgingRelease() являются макросами вокруг атрибутов компилятора. Не стесняйтесь использовать. Мне нравится API-вариант, поскольку он более распространен в наших кодовых базах, и он более явно/менее запутан.

CFBridgingRetain() эффективно удерживает объект, который должен быть сбалансирован с помощью CFBridgingRelease(). Также происходит возврат a CFTypeRef, который совместим с приведением в void*. CFBridgingRelease() эффективно отменяет сохранение и, следовательно, q останется действительным только в пределах области действия o.

Действует для базовых обратных вызовов, но вы, вероятно, не знаете, что с тегом типа void *context;, которое нужно придерживаться некоторое время. Для этого:

void callback(void *context)
{
    // grab an ARC aware reference without impacting hard-retain
    NSObject* o = (__bridge NSObject *)(context);
    NSLog(@"%@", o);
}

void freeContext(void *context)
{
    // release the hard-retain
    CFBridgingRelease(context);
}

Обратите внимание, что Xcode неплохо говорит о том, что вы должны делать, если не выполняете вызов cast/API. Это даже объясняет значения каждого из альтернативных решений (я полагался на это сильно, пока не смог удержать их прямо в моей голове).

Ответ 2

Я предполагаю, что вы используете ARC. Вы можете использовать что-то подобное при вызове myFunction

id ref = ...; // your Objective-C object
myFunction(callback, (__bridge_retained void *) ref);

В своем обратном вызове вы должны передать право собственности:

void callback(void* refPtr) {
    id refObj = (__bridge_transfer id) refPtr;
}

Замените id на свой тип объекта как присвоенный.

Ответ 3

Ответ: никоим образом. void * неявно совместим с любым типом указателя, поэтому, если у вас есть объект, который является указателем типа id (псевдоним для struct objc_object *), вы можете просто передать его, где требуется указатель void, без кастинга. Пример:

// this is the declaration of the callback function:
void callback(void *context);

// then you can call it like this:
SomeClass *obj = [[SomeClass alloc] init];
callback(obj);