Question

veux passer boost :: bind à une méthode qui attend un pointeur de fonction simple (même signature).

typedef void TriggerProc_type(Variable*,void*);
void InitVariable(TriggerProc_type *proc);
boost::function<void (Variable*, void*)> triggerProc ...
InitVariable(triggerProc);

error C2664: 'InitVariable' : cannot convert parameter 1 from 
'boost::function<Signature>' to 'void (__cdecl *)(type *,void *)'

Je peux éviter de stocker une fonction boost :: et simplement passer le foncteur lié directement, mais j'obtiens une erreur similaire:

error C2664: 'blah(void (__cdecl *)(type *,void *))' : cannot convert parameter
1 from 'boost::_bi::bind_t<R,F,L>' to 'void (__cdecl *)(type *,void *)'
Était-ce utile?

La solution

Quelqu'un a-t-il remarqué que la réponse acceptée ne fonctionne que dans des cas triviaux? La seule façon dont la fonction & Lt; & Gt; :: target () renvoie un objet pouvant être lié à un rappel C, est si elle a été construite avec un objet pouvant être lié à un rappel C. Si c'est le cas, vous auriez pu le relier directement et ignorer toute la fonction & Lt; & Gt; un non-sens pour commencer.

Si vous y réfléchissez, il n’ya pas de solution magique à cela. Un rappel de style C est stocké en tant que pointeur unique qui pointe vers le code exécutable. Tout boost non trivial :: function & Lt; & Gt; va avoir besoin d’au moins deux pointeurs: l’un sur le code exécutable, l’autre sur les données nécessaires à la configuration de l’appel (par exemple, le pointeur «this» dans le cas d’une fonction membre liée).

La bonne façon d'utiliser boost :: function et boost :: bind avec les callbacks en C est de créer une fonction de shim qui réponde à la signature du callback, détermine quelle fonction < > appeler et l'appelle. Habituellement, les callbacks C ont une sorte de vide * pour les 'données utilisateur'; c'est là que vous rangez le pointeur de votre fonction:

typedef void (*CallbackType)(int x, void* user_data);
void RegisterCallback(CallbackType cb, void* user_data);

void MyCallback(int x, void* userData) {
  boost::function<void(int)> pfn = static_cast<boost::function<void(int)> >(userData);
  pfn(x);
}

boost::function<void(int)> fn = boost::bind(myFunction(5));
RegisterCallback(MyCallback, &fn);

Bien sûr, si votre signature de rappel n'inclut pas un type de pointeur de données utilisateur, vous n'avez pas de chance. Cependant, tout rappel n'incluant pas de pointeur de données utilisateur est déjà inutilisable dans la plupart des scénarios réels et doit être réécrit.

Autres conseils

Je pense que vous souhaitez utiliser la fonction membre target () de boost :: function (n'est-ce pas une bouchée ...)

#include <boost/function.hpp>
#include <iostream>

int f(int x)
{
  return x + x;
}

typedef int (*pointer_to_func)(int);

int
main()
{
  boost::function<int(int x)> g(f);

  if(*g.target<pointer_to_func>() == f) {
    std::cout << "g contains f" << std::endl;
  } else {
    std::cout << "g does not contain f" << std::endl;
  }

  return 0;
}
  

pouvez-vous le faire fonctionner avec bind?

cb_t cb = *g.target<cb_t>(); //target returns null

Il s'agit de de par sa conception . Fondamentalement, puisque bind renvoie un type complètement différent, cela ne fonctionnera pas. Fondamentalement, un objet proxy de classeur ne peut pas être converti en un pointeur de fonction C (puisqu'il n'en est pas un: c'est un objet de fonction). Le type renvoyé par boost::bind est compliqué. Le standard C ++ actuel ne permet pas de faire ce que vous voulez. C ++ 0x sera associé à une decltype expression qui pourrait être utilisée ici pour obtenir quelque chose comme ceci:

typedef decltype(bind(f, 3)) bind_t;
bind_t target = *g.target<bind_t>();

Notez que cela pourrait ou non fonctionner. Je n'ai aucun moyen de le tester.

pouvez-vous le faire fonctionner avec bind?

#include <boost/function.hpp>
#include <boost/bind.hpp>

void f(int x)
{
    (void) x;
    _asm int 3;
}

typedef void (*cb_t)(int);

int main()
{
    boost::function<void (int x)> g = boost::bind(f, 3);
    cb_t cb = *g.target<cb_t>(); //target returns null
    cb(1);

    return 0;
}

update: OK, l’objectif est de lier une méthode à un rappel de fonction. alors maintenant quoi?

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