Question

Tout d’abord, je dois admettre que mes compétences en programmation sont plutôt limitées et j’ai repris un projet (très petit) OOP C ++ existant dans lequel j’essaie d’intervenir moi-même. Malheureusement, je rencontre un problème qui va au-delà. mes connaissances et j'espère trouver de l'aide ici. Je travaille avec une bibliothèque tierce (qui ne peut pas être modifiée) pour récupérer des images à partir d'une caméra. Nous utiliserons ici quelques noms d'espaces réservés.

La bibliothèque tierce a la fonction "ThirdPartyGrab". pour démarrer une capture en direct continue et prend un pointeur sur une fonction qui sera appelée à chaque fois qu'une nouvelle image arrive. Donc, dans une application C normale, ça se passe comme ça:

ThirdPartyGrab (HookFunction);

"HookFunction" doit être déclaré comme:

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

ou "BUF_HOOK_FUNCTION_PTR" qui est déclaré comme

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

J'ai maintenant une application C ++ et une classe "MyFrameGrabber". qui devrait résumer tout ce que je fais. Donc, je mets dans la fonction crochet en tant que membre privé comme ceci:

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

Il existe également une fonction d’annulation publique "StartGrab". dans ma classe qui devrait commencer le Grab. À l'intérieur, j'essaie d'appeler:

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

qui (sans surprise) échoue. Il indique que l'appel de fonction à MyFrameGrabber :: HookFunction manque de la liste d'arguments et que je devrais essayer d'utiliser & MyFrameGrabber :: HookFunction pour créer un pointeur à la place. Toutefois, en passant "& MyFrameGrabber :: HookFunction". à la place, il en résulte une autre erreur indiquant que cela ne peut pas être converti en BUF_HOOK_FUNCTION_PTR.

Après avoir lu les pointeurs de fonction FAQ C ++ Je pense comprendre le problème mais je ne peux pas trouver de solution. J'ai essayé de rendre la fonction de crochet statique, mais cela entraîne également une erreur de conversion. J'ai également pensé à placer la fonction hook en dehors de la classe, mais je dois utiliser des fonctions de classe dans la fonction hook. Existe-t-il un autre moyen ou dois-je changer tout mon concept?

EDIT 14.01.08: J'ai testé la solution de contournement singleton, car je ne peux pas modifier la bibliothèque tierce et le pointeur void concerne uniquement les données utilisées dans la fonction de raccordement. Malheureusement, cela n’a pas fonctionné correctement, comme je l’espérais .... Je ne sais pas si la fonction statique doit figurer dans une classe distincte, je l’ai donc placée dans mon "MyFrameGrabber". classe:

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, ...);
}

Dans mon fichier cpp, j'ai la fonction call_hook:

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

Mais cela me donne une erreur dans statique MatroxFrameGrabber _instance; , selon lequel aucun constructeur standard correspondant n’a été trouvé. C'est exact parce que mon constructeur MyFrameGrabber ressemble à ceci:

<*>

J'ai essayé d'insérer un constructeur vide MyFrameGrabber (); , mais cela a entraîné une erreur de l'éditeur de liens. Dois-je transmettre des paramètres vides au constructeur MyFrameGrabber dans le singleton? Ou dois-je avoir une classe de crochet distincte et si oui, comment puis-je accéder aux fonctions MyFrameGrabber? Merci d'avance.

SECOND EDIT 15.01.08: J'ai appliqué les modifications et il compile et lie maintenant. Malheureusement, je ne peux pas encore tester cela au moment de l'exécution car c'est une DLL et je n'ai pas encore de Debug Caller Exe. D'autres problèmes sont survenus lors de l'initialisation, etc.

Était-ce utile?

La solution

La raison & amp;; MyFrameGrabber :: HookFunction " BUF_HOOK_FUNCTION_PTR ne peut pas être converti car, en tant que membre de la classe, il a implicitement comme premier paramètre le "this" pointeur, vous ne pouvez donc pas convertir une fonction membre en une fonction non-membre: les deux signatures se ressemblent mais sont en réalité différentes.

Je déclarerais une interface, définirais la fonction à appeler, demanderait à votre classe de la mettre en œuvre et de transmettre l'objet lui-même à la place du rappel (vous pouvez penser à une interface comme au remplacement orienté objet d'un pointeur de fonction):

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

// nouvelle définition: ThirdPartyGrab (..., IHookInterface, ...);

EDITER - autre solution possible si vous ne pouvez pas modifier la bibliothèque: utilisez un singleton plutôt qu'une fonction statique.

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);
}

SECOND EDIT: vous pouvez légèrement modifier la classe singleton avec une méthode d’initialisation pour appeler le constructeur avec les paramètres appropriés, mais elle n’est peut-être pas plus élégante que la solution suivante, plus simple:

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, ...);
}

Autres conseils

Votre méthode de membre privé a un premier point avec un ce implicite. Si vous écrivez cela, il est évident que les signatures de fonction ne correspondent pas.

Vous devez écrire une fonction membre statique, qui peut être transmise à la bibliothèque en tant que fonction de rappel. Le dernier argument du HookFunction , un void * , me ressemble beaucoup à un cookie, dans lequel on peut passer son propre pointeur.

Donc, dans l'ensemble, cela devrait ressembler à ceci:

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, ...);
  }
};

Ceci ne fonctionne bien sûr que si l'argument void * fait ce que j'ai dit. La position du this dans l'appel ThirdPartyGrab () doit être facile à trouver lorsque la signature de fonction complète, y compris les noms de paramètre disponibles.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top