Início > C++ > Implementar um callback com métodos em C++

Implementar um callback com métodos em C++

Funções comuns em C e métodos não estáticos em C++ têm assinaturas diferentes, incompatíveis portanto. Mas o que acontece se você quer/precisa implementar uma função callback em C++ que precisa ter a mesma assinatura em C?

Por exemplo, na API da opengl existe callbacks C. E eu gostaria de criar um objeto que implemente métdodos que devem ser passados para essas funções da API. Mas simplesmente criar um objeto que implemente tais métodos não adiantará, pois objetos precisam de um ponteiro ‘this’, o que torna as assinaturas entre funções C (ou métodos estáticos C++) incompatíveis com métodos não estáticos C++.

Para contornar esse problema existem algumas maneiras. Irei mostrar 2 maneiras, as que considero mais simples.

Primeiramente para ambas as maneiras que comentarei aqui, é nessário uma função estática auxiliar. Esta função tem o objetivo de satisfazer a assinatura do callback.

Para a primeira maneira, simplesmente coloque como argumento do método estático um ponteiro para um objeto que implemente a função que queira usar. Claro, isso só pode ser feito se também for possível modificar a assinatura de quem chama o callback – portanto, sim, essa maneira é bastante inútil, já que se for possivel mudar a assinatura da função do callback, então certamente há caminhos mais interessantes a ser seguido. Contudo, se a função esperar void* ao invés de um objeto de alguma classe (como em: void funcao( void* obj, void (*func)(void*,char*) ) ) então pode ser interessante seguir este caminho (é comum em bibliotecas para paralelismo) – só terá que fazer os devidos casts. (No site referência tem um exemplo de como implementar caso tenha um ponteiro para void*)

De qualquer maneira, aqui tem um exemplo usando uma classe qualquer:


#include <isotream>

using namespace std;

class TClass{
      public:
            void umaFuncao(char* texto){cout << texto << endl;}
            static void wrapper(TClass* obj, char* t){obj->umaFuncao(t);}
};

void funcaoComCallback(TClass* objeto, void (*func)(TClass*,char*)){
      func(objeto,"imprime um texto"); //faça o callback..
}

void umExemploDeUso(){
      TClass a; //objeto exemplo
      funcaoComCallback(&a,TClass::wrapper);
}

A segunda maneira é, na minha opnião, mais interessante. Não é necessário mudar a assinatura da função com callback, mas ainda é necessário uma função estática. O que acontece é que teremos um objeto ‘global’ que será chamado pela nossa função estática.

Mais ou menos assim:


#include <iostream>

using namespace std;

class TClass{
      public:
            static TClass* aux;
            void umaFuncao(char* texto){cout << texto << endl;
            static void wrapper(char* texto){aux->umaFuncao(texto);}
};

void funcaoQualquer(void (*func)(char* t)){
      func("texto qualquer");
}

//primeiro inicie o ponteiro aux
TClass* TClass::aux; //= new TClass;

void exemploDeUso(){
      TClass a;
      TClass::aux = &a;
      funcaoQualquer(TClass::wrapper);
}

link referência

CategoriasC++ Tags:,
  1. Nenhum comentário ainda.
  1. fevereiro 20, 2010 às 1:43 am | #1

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Sair / Alterar )

Imagem do Twitter

You are commenting using your Twitter account. Sair / Alterar )

Foto do Facebook

You are commenting using your Facebook account. Sair / Alterar )

Connecting to %s

Seguir

Obtenha todo post novo entregue na sua caixa de entrada.