Pergunta

Primeiro de tudo eu tenho que admitir que minhas habilidades de programação são muito limitados e assumi um (muito pequeno) projeto C ++ OOP existente onde eu tentar empurrar meu próprio material. Infelizmente eu estou enfrentando um problema que vai além meu conhecimento e espero encontrar alguma ajuda aqui. Eu estou trabalhando com uma biblioteca de terceiros (que não pode ser alterado) para pegar imagens de uma câmera e vai usar alguns nomes de espaço reservado aqui.

A biblioteca de terceiros tem uma função "ThirdPartyGrab" para iniciar uma garra ao vivo contínua e leva um ponteiro para uma função que será chamado cada vez que um novo quadro chega. Assim, em uma aplicação normal C vai como esta:

ThirdPartyGrab (HookFunction);

necessidades "HookFunction" para ser declarado como:

long _stdcall HookFunction (long, long, void*);

ou "BUF_HOOK_FUNCTION_PTR", que é declarado como

typedef long (_stdcall *HOOK_FUNCTION_PTR) (long, long, void*);

Agora eu tenho um aplicativo C ++ e uma classe "MyFrameGrabber", que deve encapsular tudo o que faço. Então eu coloquei na função de gancho como um membro privado como este:

long _stdcall HookFunction (long, long, void*);

Também há uma função void "StartGrab" público na minha classe que deve iniciar o Grab. Dentro tento chamada:

ThirdPartyGrab (..., HookFunction, ...);

que (não surpreendentemente) falhar. Ele diz que a chamada de função para MyFrameGrabber :: HookFunction perde a lista de argumentos e eu deveria tentar usar & MyFrameGrabber :: HookFunction para criar um ponteiro em vez. No entanto passando "& MyFrameGrabber :: HookFunction" em vez resulta em outro erro que não pode ser convertido em BUF_HOOK_FUNCTION_PTR.

Depois de ler os ponteiros C ++ FAQ função Eu acho que entendo o problema, mas não pode fazer-se uma solução. Eu tentei fazer a função de gancho estático, mas isso também resulta em um erro de conversão. Também pensei em colocar a função de gancho fora da classe, mas eu preciso para funções de classe utilização dentro da função de gancho. Existe outra maneira ou que eu preciso mudar todo o meu conceito?

EDIT 14.01.08: Eu testei a solução singleton desde que eu não posso mudar a biblioteca de terceiros eo ponteiro nulo é apenas para dados que são usados ??dentro da função de gancho. Infelizmente não trabalhou fora da caixa como eu esperava .... Eu não sei se as necessidades função estática para estar em uma classe separada assim que eu colocá-lo na minha classe "MyFrameGrabber":

static MyFrameGrabber& instance()
{
        static MyFrameGrabber _instance;
        return _instance;
}
long Hook(long, long, void*); // Implementation is in a separate cpp file

No meu arquivo cpp Eu tenho a função call_hook:

long MFTYPE call_hook(long x, MIL_ID y, void MPTYPE *z)
{
    return MyFrameGrabber::instance().Hook(x,y,z);
}
void
MyFrameGrabber::grab ()
{
    ThirdPartyGrab(..., call_hook, ...);
}

Mas isso me dá um erro no static MatroxFrameGrabber _instance; que nenhum construtor padrão correspondente for encontrado. Isso é correto porque meus MyFrameGrabber construtor esta aparência:

MyFrameGrabber (void* x,
                const std::string &y, int z,
                std::string &zz);

Eu tentei colocar em uma MyFrameGrabber(); construtor vazio, mas isso resulta em um erro de vinculador. Devo passar parâmetros vazios para o construtor MyFrameGrabber no singleton? Ou eu preciso para ter um gancho separado Classe e se sim como eu poderia acessar MyFrameGrabber funções? Desde já, obrigado.

SEGUNDO EDIT 15.01.08: Eu apliquei as alterações e ele compila e links agora. Infelizmente, não posso testar isso em tempo de execução ainda porque é uma DLL e não tenho Debug Caller Exe e ainda há outros problemas durante a inicialização etc. I vai marcar o post como resposta, porque eu tenho certeza que este é o caminho certo para fazer isso.

Foi útil?

Solução

A razão "& MyFrameGrabber :: HookFunction" não pode ser convertido para um BUF_HOOK_FUNCTION_PTR é que, sendo um membro da classe, tem implicitamente como primeiro parâmetro o ponteiro "este", portanto, você não pode converter uma função de membro para um não- função membro: as duas assinaturas têm a mesma aparência, mas são realmente diferentes

.

Gostaria de declarar uma interface, definindo a função de chamada, tem a sua classe implementá-lo e passar o objeto em si, em vez da chamada de retorno (você pode pensar em uma interface como a substituição orientada a objeto de um ponteiro de função):

class IHookInterface{
public:
    virtual long HookFunction(long, long, void*) = 0;
};
 class HookClass : public IHookInterface{
public:
    virtual long Hook(long, long, void*) {
        // your code here... 
    }
};

// nova definição: ThirdPartyGrab (..., IHookInterface, ...);

.

EDIT - outra solução possível no caso de você não pode modificar a biblioteca: usar um singleton em vez de uma função estática

class HookClass{
public:
    static HookClass& instance(){
        static HookClass _instance;
        return _instance;
    }
    long Hook(long, long, void*) {
        // your code here... 
    }
};

long call_hook(long x,long y,void * z){
    return HookClass::instance().Hook(x,y,z);
}

SEGUNDO EDIT: você pode modificar ligeiramente a única classe com um método de inicialização para chamar o construtor com os parâmetros adequados, mas talvez ele não é mais elegante do que a solução a seguir, que é mais simples:

class HookClass{
public:

    HookClass(string x,string y...){
    }

    long Hook(long, long, void*) {
        // your code here... 
    }
};

static HookClass * hook_instance = 0;

long call_hook(long x,long y,void * z){
    if (0 != hook_instance){
        return hook_instance->Hook(x,y,z);
    }
}

int main(){
    hook_instance = new HookClass("x","y");
    ThirdPartyGrab(..., call_hook, ...);
}

Outras dicas

Seu método de membro privado tem um ponteiro this implícito como primeiro argumento. Se você escrever isso, é óbvio que as assinaturas de função não coincidem.

Você precisa escrever uma função de membro estático, que pode ser passado como o retorno de chamada função para a biblioteca. O último argumento do HookFunction, um void*, parece-me muito bem como um cookie, onde se pode passar uns próprio ponteiro na.

Assim, apesar de tudo, deve ser algo como isto:

class MyClass {
  long MyCallback(long, long) {
    // implement your callback code here
  }

  static long __stdcall ThirdPartyGrabCallback(long a, long b, void* self) {
    return reinterpret_cast<MyClass*>(self)->MyCallback(a, b);
  }
public:
  void StartGrab() {
    ThirdPartyGrab(..., &MyClass::ThirdPartyGrabCallback, ..., this, ...);
  }
};

Isto, obviamente, só funciona se o argumento void* está fazendo o que eu disse. A posição do this na chamada ThirdPartyGrab() deve ser fácil de encontrar quando se tem a assinatura da função completa, incluindo os nomes dos parâmetros disponíveis.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top