Как передать функцию не статического члена в качестве обратного вызова? - PullRequest
7 голосов
/ 20 января 2010

<code> 
io_iterator_t enumerator;
kern_return_t   result;
result = IOServiceAddMatchingNotification(
             mNotifyPort,
             kIOMatchedNotification,
             IOServiceMatching( "IOFireWireLocalNode" ),
             serviceMatchingCallback, 
             (void *)0x1234,
             & enumerator );
<code>
serviceMatchingCallback((void *)0x1234, enumerator);

Если я объявляю serviceMatchinCallback как статический, он работает, но я не хочу, чтобы он был статическим. Есть ли способ передать ему нестатическую функцию обратного вызова?

Спасибо

Ответы [ 8 ]

7 голосов
/ 20 января 2010

Прототип для IOServiceMatchingCallback не совместим с нестатическим методом класса (и технически не совместим с методом статического класса либо ), поэтому вы не собираетесь в состоянии использовать это.

Но, к счастью, IOServiceAddMatchingNotification поддерживает указатель контекста (или, как они его называют, refCon), который позволит вам создать thunk, который не зависит от глобальных данных.

Вам нужно определить обратный вызов с совместимой связью (т.е. extern "C"). Эта функция приведёт ваш refCon к указателю вашего объекта, а затем перенаправит вызов вашему экземпляру метода:

extern "C"
void io_callback(void *refcon, io_iterator_t iterator)
{
    myclass *c = static_cast<myclass *>(refcon);
    c->real_callback(iterator);
}

Затем, когда вы вызываете IOServiceAddMatchingNotification, обязательно передайте указатель на ваш объект для refCon (здесь я предполагаю, что вы вызываете IOServiceAddMatchingNotification из функции-члена, и у вас есть указатель this):

result = IOServiceAddMatchingNotification(
             mNotifyPort,
             kIOMatchedNotification,
             IOServiceMatching( "IOFireWireLocalNode" ),
             serviceMatchingCallback, 
             this,
             &enumerator );
4 голосов
/ 20 января 2010

Вы можете сохранить его статическим, но использовать userdata для хранения указателя this в дополнение к любым другим userdata, которые вы хотите (например, упаковав их в структуру), а затем вызывать специфичный для объекта обратный вызов из static версия путем вызова this->someCallback (где this - это указатель, сохраненный в пользовательских данных, конечно).

2 голосов
/ 20 января 2010

Не напрямую.

Указатель нестатической функции (известный как указатель на функцию-член) имеет скрытый параметр this, поэтому типы не совпадают.Статическая функция не имеет указателя «this».

Чтобы обойти это, вы должны иметь возможность передавать элемент данных пользователя, который является указателем «this» объекта, который вы хотите использовать в качестве обратного вызова.,Затем укажите статический член, которому передаются пользовательские данные, преобразует его в указатель на объект класса и вызывает для него нестатический член.

Глядя на опубликованный вами код, трудноскажите, существует ли объект пользовательских данных, возможно, параметр last-but = one.

0 голосов
/ 20 января 2010

EDIT Я только что заметил, что вы используете API пользовательского пространства IOKit, а не сторону kext, что делает этот пост неуместным.


Предполагая, что вы работаете в ядре OS X, вы действительно можете это сделать. Вы можете использовать макрос OSMemberFunctionCast для преобразования указателя на функцию-член в простой указатель на функцию C, обратите внимание, что он должен вызываться с первым аргументом, указывающим на экземпляр класса, например.

IOServiceMatchingCallback mycb = OSMemberFunctionCast(IOServiceMatchingCallback,
    &myclassinstance, &MyClass::cb_method);

result = IOServiceAddMatchingNotification(
             mNotifyPort,
             kIOMatchedNotification,
             IOServiceMatching( "IOFireWireLocalNode" ),
             mycb,
             &myclassinstance,
             &enumerator);
0 голосов
/ 20 января 2010

если вы поместите эту строку в свой конструктор (или в любой метод экземпляра), то вы сможете сделать this.instanceMethod () для ссылки на метод экземпляра.

0 голосов
/ 20 января 2010

Функция, отличная от static, имеет неявный параметр this и, следовательно, будет иметь неправильную сигнатуру для обратного вызова.

Извините, простой способ избежать острова перехода.

0 голосов
/ 20 января 2010

Нет.Нестатическим методам нужен объект для работы.Если вы просто передадите метод, вам также понадобится какой-то способ сообщить функции, для какого объекта вызывать метод.

0 голосов
/ 20 января 2010

Нет, нестатический член ожидает объект, а вызывающая сторона (обратный вызов) не имеет и не будет предоставлять его.

...