Pergunta

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

serviceMatchingCallback((void *)0x1234, enumerator);

Se eu declarar o Servicematchincallback como estático, ele funciona, mas não quero que seja estático. Existe uma maneira de passar por uma função de retorno de chamada não estática?

obrigada

Foi útil?

Solução

Você pode mantê -lo estático, mas use os dados do usuário para armazenar o this Ponteiro Além de qualquer outro data do usuário que você quiser (embalando-os em uma estrutura, por exemplo) e depois chamar um retorno de chamada específico para o objeto da versão estática chamando this->someCallback (Onde this é o ponteiro armazenado nos dados do usuário, é claro).

Outras dicas

O protótipo para IoservicematchingCallback não é compatível com um método de classe não estático (e tecnicamente é não é compatível com um método de classe estática também), então você não poderá usar isso.

Mas felizmente IoserviceaddMatchingNotification Suporta um ponteiro de contexto (ou como eles chamam, um refcon) que permitirá que você crie um Thunk que não depende de dados globais.

Você precisa definir um retorno de chamada com a ligação compatível (ou seja, extern "C"). Esta função lançará seu refcon para o seu ponteiro de objeto e encaminhará a chamada para o método da sua instância:

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

Então, quando você ligar para o iServiceaddMatchingNotification, passe um ponteiro para o seu objeto para refcon (aqui estou supondo que você ligue para ioserviceaddmatchingNotification de uma função de membro e você tem um ponteiro):

result = IOServiceAddMatchingNotification(
             mNotifyPort,
             kIOMatchedNotification,
             IOServiceMatching( "IOFireWireLocalNode" ),
             serviceMatchingCallback, 
             this,
             &enumerator );

Não diretamente.

O ponteiro não estático da função (conhecido como ponteiro de função de membro) possui um parâmetro 'este' oculto para que os tipos não correspondam. A função estática não tem 'este ponteiro'.

Para contornar isso, você precisa passar em um item de dados do usuário, que é o ponteiro 'Este' do objeto que você deseja usar como retorno de chamada. Em seguida, especifique um membro estático que seja aprovado nos dados do usuário, converte-os em um ponteiro para o objeto de classe e chama o membro não estático nele.

Olhando para o código que você postou, é difícil saber se existe um objeto de dados do usuário, possivelmente o parâmetro Último, mas um.

Não, um membro não estático esperaria um objeto e o chamador (zagueiro) não possui e não fornecerá um.

Não. Os métodos não estáticos precisam de um objeto para operar. Se você apenas passe o método, também precisaria de uma maneira de dizer à função em qual objeto chamar o método.

Um nãostatic A função tem um implícito this parâmetro e, portanto, teria a assinatura errada para o retorno de chamada.

Desculpe, não é uma maneira fácil de evitar a Ilha Jump.

Se você colocar essa linha no seu construtor (ou em qualquer método de instância), poderá fazer isso.instancemethod () para consultar o método da instância.

EDITARAcabei de notar que você está usando a API IOKIT do espaço do usuário, não o lado Kext, o que torna este post irrelevante.


Supondo que você esteja trabalhando no kernel do OS X, você pode realmente fazer isso. Você pode usar o OSMemberFunctionCast Macro para converter um ponteiro de função de membro em um ponteiro de função c simples, observe que ele deve ser chamado com o primeiro argumento apontando para uma instância da classe, por exemplo.

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

result = IOServiceAddMatchingNotification(
             mNotifyPort,
             kIOMatchedNotification,
             IOServiceMatching( "IOFireWireLocalNode" ),
             mycb,
             &myclassinstance,
             &enumerator);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top