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

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

  myFunction (MyProc callback, void * ref)

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

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

Как я могу разыграть NSObject в пустоту * и как я разыгрываю пустоту * как NSObject.

Заранее спасибо.

Ответы на вопрос(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);
 user52975816 окт. 2012 г., 16:15
@BenSmiley хм. Попробуйте отключить ARC на некоторое время, затем повторите попытку. Что это делает?
 user52975816 окт. 2012 г., 18:45
@bbum Спасибо за разъяснения. Кстати, знает ли ARC о типах CoreFoundation? Если нет, то почему кастингCFTypeRef вvoid * необходимо? (Я действительно ненавижу ARC. Это должно было сделать программистов жизнь проще, но есть так много исключений и угловых случаев, не говоря уже об уродливых квалификаторах, связанных с собственностью, с префиксомдвойное подчеркивание что на самом деле я считаю MRC намного проще, чем ARC.)
 Ben Smiley16 окт. 2012 г., 16:19
Без ARC это работает. Но я'Я планирую использовать ARC для этого проекта.
 Ben Smiley16 окт. 2012 г., 16:10
Когда я пытаюсь пройтисамость» к функции я получаю предупреждение компилятора: говоря, что неявное преобразование указателя Objective-C в тип указателя C void * требует преобразования моста.
 user52975816 окт. 2012 г., 16:44
@BenSmiley в этом случае, вы можете привести его к(__strong id)Надеюсь, это наконец-то сработает ... (Черт возьми!)
 bbum16 окт. 2012 г., 18:46
Цель ARC - узнать о CFType 'с, но яЯ не уверен, сколько поддержки в ToT. Не та верхушка дереваs анализатор также поддерживает проверку malloc () / free (). Я подозреваю, что приведение требуется именно потому, что цель - сделать так, чтобы компилятор также полностью знал о CFTypes, но яЯ должен спросить.
 bbum16 окт. 2012 г., 18:30
Первая строка вашего ответа говоритнедействительным неявно совместим с любым типом указателя *.id тип указателя Это н'совместим сvoid* под ARC. Таким образом, это утверждение не соответствует действительности.
 Ben Smiley16 окт. 2012 г., 16:15
Когда я выполняю связующее действие, я получаю исключение BAD_ACCESS, приводящее void * обратно к объекту Objective-C.
 user52975816 окт. 2012 г., 18:28
@bbumЯ никогда не говорилid а такжеvoid * были одно и то же! я сказал чтоvoid * неявно совместим с любым типом указателя данных в C.
 bbum16 окт. 2012 г., 18:38
В частности, потому что вы бросили междуvoid* а такжеid без явного объявления намерений подсчета ссылок по всему составу. Таким образом, голые броски больше не возможны, что является специфическим отклонением от "void* это тип указателя где угодно / везде " мантра кл.
 user52975816 окт. 2012 г., 16:10
@BenSmiley когда ты это сделаешь (что?), Тогда что?
 bbum16 окт. 2012 г., 18:42
Нет, дело в том, что тыделать должны быть разыграны, потому что для разыгрывания требуется дополнительная аннотация. Подразумеваемые приведения больше не работают (потому что они были источником многих действительно неприятных для исправления сбоев при интеграции библиотек C в код Objective-C). Действительно, это явное приведение отid вCFTypeRef, Как только это будет сделано,void* работает с этим результатом так же, как обычно (хотя ->CFTypeRef void* требуемый актерский состав, который вы видите в моем примере, который кажется ... другим, но предпочтительным).
 bbum16 окт. 2012 г., 18:26
Это больше не относится к компилятору ARC, потому чтоid а такжеvoid* это не одно и то же. Это решение было принято именно потому, что междуvoid* а такжеid были изобиловали ошибками. Операторы / API-операторы приведения были созданы для явной поддержки таким способом, о котором может рассуждать как компилятор, так и разработчик должен явно выражать намерение.
 user52975816 окт. 2012 г., 18:38
@bbum "вы выполняете между void * и id без явного объявления намерений подсчета ссылок " <- нетв тот момент, что вы нели вообще на кастинг?
Решение Вопроса

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

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(), Бывает и вернуть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. Это даже объясняет значение каждого из альтернативных решений (я сильно полагался на это, пока не смог сохранить)прямо в моей голове).

что вы используете 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 с вашим типом объекта, как присвоено.

 tia16 окт. 2012 г., 17:09
Я положилcallback функционировать в моем тестовом проекте точно так же, как я публикую здесь, и я нене вижу такой ошибки компиляции. Вы можете попробовать это?
 Ben Smiley16 окт. 2012 г., 16:28
Когда я пытаюсь привести к идентификатору, он говорит: Несовместимые типы приводят void * к идентификатору с передачей по мосту.

Ваш ответ на вопрос