Seulement j'aimerai incorporer ces fonctions de callback au sein d'une
classe. Seulement bien sûr je ne peux pas attribuer un pointeur de
fonction membre.
J'ai contourné le problème en définissant une fonction membre statique,
qui redirige vers une fonction membre non statique, via un pointeur de la
classe statique.
Je ne pense pas que ce que je viens de dire soit d'une clarté absolue,
donc un petit exemple...
class foo
{
private:
static foo * f;
static void StaticOnFrameMove( int i);
Seulement j'aimerai incorporer ces fonctions de callback au sein d'une classe. Seulement bien sûr je ne peux pas attribuer un pointeur de fonction membre.
Ni même, si l'API est définie en C, une fonction qui n'est pas « extern "C" ».
J'ai contourné le problème en définissant une fonction membre statique, qui redirige vers une fonction membre non statique, via un pointeur de la classe statique.
Je ne connais pas l'API que tu utilises, mais la plupart de temps, en plus de l'adresse de la fonction, tu passes un pointeur à des données (un void*) -- c'est le cas de tous les interfaces bien conçues, et c'est le cas, d'après ce que j'ai entendu dire, de la plupart des call-backs dans l'API de Windows. La solution classique est alors quelque chose du genre :
extern "C" void /* ou ce qu'il faut, évidemment */ callback( void* p ) { static_cast< MaClasse* >( p )->laFonctionQuIlFaut() ; }
On passe alors l'adresse de callback, et l'adresse de l'objet.
(Ce qu'on aimerait, ici, c'est un espèce de template pour callback. Ce que le « extern "C" » rend impossible. Reste les macros, si le cas se présente souvent.)
Je ne pense pas que ce que je viens de dire soit d'une clarté absolue,
Mais si... C'est un problème on ne peut plus connu, du fait qu'il y a tellement d'API définies en C.
[...]
Est-ce une manière courante de fonctionner? Sinon quelles autres alternatives s'offrent à moi?
S'il n'y a pas de paramètre void*, il n'y a pas beaucoup d'autres solutions. Mais il pose un problème dès qu'on veut inscrire la même fonction plusieurs fois, mais sur des données différentes.
Parfois, tu peux le contourner aussi avec un std::map et d'autres informations. Si, par exemple, tu as un callback par élément graphique, et que l'API te donne une indentificateur de l'élément graphique, tu peux faire quelque chose du genre :
static std::map< GUIId, MaClasse* > objectMap ;
extern "C" void callback( CUIId id ) { objectMap[ id ]->f() ; }
-- James Kanze Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
Michael wrote:
j'ai Windows qui me cause quelques soucis, liés à des
callbacks de fonction.
J'ai par exemple le pointeur de fonction suivant:
typedef void (*LPDXUTCALLBACKFRAMEMOVE)( int i );
J'ai la fonction suivante qui permet d'attribuer un callback:
Seulement j'aimerai incorporer ces fonctions de callback au
sein d'une classe. Seulement bien sûr je ne peux pas attribuer
un pointeur de fonction membre.
Ni même, si l'API est définie en C, une fonction qui n'est pas
« extern "C" ».
J'ai contourné le problème en définissant une fonction membre
statique, qui redirige vers une fonction membre non statique,
via un pointeur de la classe statique.
Je ne connais pas l'API que tu utilises, mais la plupart de
temps, en plus de l'adresse de la fonction, tu passes un
pointeur à des données (un void*) -- c'est le cas de tous les
interfaces bien conçues, et c'est le cas, d'après ce que j'ai
entendu dire, de la plupart des call-backs dans l'API de
Windows. La solution classique est alors quelque chose du
genre :
extern "C" void /* ou ce qu'il faut, évidemment */
callback( void* p )
{
static_cast< MaClasse* >( p )->laFonctionQuIlFaut() ;
}
On passe alors l'adresse de callback, et l'adresse de l'objet.
(Ce qu'on aimerait, ici, c'est un espèce de template pour
callback. Ce que le « extern "C" » rend impossible. Reste les
macros, si le cas se présente souvent.)
Je ne pense pas que ce que je viens de dire soit d'une clarté
absolue,
Mais si... C'est un problème on ne peut plus connu, du fait
qu'il y a tellement d'API définies en C.
[...]
Est-ce une manière courante de fonctionner? Sinon quelles
autres alternatives s'offrent à moi?
S'il n'y a pas de paramètre void*, il n'y a pas beaucoup
d'autres solutions. Mais il pose un problème dès qu'on veut
inscrire la même fonction plusieurs fois, mais sur des données
différentes.
Parfois, tu peux le contourner aussi avec un std::map et
d'autres informations. Si, par exemple, tu as un callback par
élément graphique, et que l'API te donne une indentificateur de
l'élément graphique, tu peux faire quelque chose du genre :
static std::map< GUIId, MaClasse* > objectMap ;
extern "C" void
callback( CUIId id )
{
objectMap[ id ]->f() ;
}
--
James Kanze kanze.james@neuf.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
Seulement j'aimerai incorporer ces fonctions de callback au sein d'une classe. Seulement bien sûr je ne peux pas attribuer un pointeur de fonction membre.
Ni même, si l'API est définie en C, une fonction qui n'est pas « extern "C" ».
J'ai contourné le problème en définissant une fonction membre statique, qui redirige vers une fonction membre non statique, via un pointeur de la classe statique.
Je ne connais pas l'API que tu utilises, mais la plupart de temps, en plus de l'adresse de la fonction, tu passes un pointeur à des données (un void*) -- c'est le cas de tous les interfaces bien conçues, et c'est le cas, d'après ce que j'ai entendu dire, de la plupart des call-backs dans l'API de Windows. La solution classique est alors quelque chose du genre :
extern "C" void /* ou ce qu'il faut, évidemment */ callback( void* p ) { static_cast< MaClasse* >( p )->laFonctionQuIlFaut() ; }
On passe alors l'adresse de callback, et l'adresse de l'objet.
(Ce qu'on aimerait, ici, c'est un espèce de template pour callback. Ce que le « extern "C" » rend impossible. Reste les macros, si le cas se présente souvent.)
Je ne pense pas que ce que je viens de dire soit d'une clarté absolue,
Mais si... C'est un problème on ne peut plus connu, du fait qu'il y a tellement d'API définies en C.
[...]
Est-ce une manière courante de fonctionner? Sinon quelles autres alternatives s'offrent à moi?
S'il n'y a pas de paramètre void*, il n'y a pas beaucoup d'autres solutions. Mais il pose un problème dès qu'on veut inscrire la même fonction plusieurs fois, mais sur des données différentes.
Parfois, tu peux le contourner aussi avec un std::map et d'autres informations. Si, par exemple, tu as un callback par élément graphique, et que l'API te donne une indentificateur de l'élément graphique, tu peux faire quelque chose du genre :
static std::map< GUIId, MaClasse* > objectMap ;
extern "C" void callback( CUIId id ) { objectMap[ id ]->f() ; }
-- James Kanze Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34