C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

comment déclarer une fonction membre comme fonction callback

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (French)
View previous topic :: View next topic  
Author Message
Eric Bart
Guest





PostPosted: Thu Aug 26, 2004 1:03 pm    Post subject: comment déclarer une fonction membre comme fonction callback Reply with quote



Bonjour,

J'aimerais utiliser une fonction membre d'une classe comme une fonction
callback.

Par exemple pour utiliser une thread :
pthread_create (&th, NULL, MaClasse::MaFonction, NULL);

Si MaFonction est déclarée en static, ça fonctionne.

Mais est-ce possible avec une fonction membre non statique ?

Il faudrait pouvoir donner dynamiquement l'adresse de la fonction ... non ?

Merci


Back to top
Loïc Joly
Guest





PostPosted: Thu Aug 26, 2004 1:30 pm    Post subject: Re: comment déclarer une fonction membre comme fonction call Reply with quote



Eric Bart wrote:

Quote:
Bonjour,

J'aimerais utiliser une fonction membre d'une classe comme une fonction
callback.

Par exemple pour utiliser une thread :
pthread_create (&th, NULL, MaClasse::MaFonction, NULL);

Si MaFonction est déclarée en static, ça fonctionne.

Mais est-ce possible avec une fonction membre non statique ?

Non.

Quote:
Il faudrait pouvoir donner dynamiquement l'adresse de la fonction ... non ?
??


La technique classique la suivante (je détaille pas trop, c'est souvent
posé ici, regarde google pour plus de détails).

void threadFct (void* data)
{
MaClasse *mc = static_cast<MaClasse*> data;
mc->MaFonction();
}

int f()
{
MaClasse c;
// ...
pthread_create (&th, NULL, &threadFct, &c);
}

--
Loîc

Back to top
Falk Tannhäuser
Guest





PostPosted: Thu Aug 26, 2004 2:15 pm    Post subject: Re: comment déclarer une fonction membre comme fonction call Reply with quote



Loïc Joly wrote:
Quote:
Eric Bart wrote:

Bonjour,

J'aimerais utiliser une fonction membre d'une classe comme une fonction
callback.

Par exemple pour utiliser une thread :
pthread_create (&th, NULL, MaClasse::MaFonction, NULL);

Si MaFonction est déclarée en static, ça fonctionne.

Même ça n'est pas garanti, car à mon avis, pthread_create nécessite
comme argument un pointeur sur une fonction qualifiée 'extern "C"'.
Les fonctions C++ et C ne sont pas forcement interchangeables entre
elles, non seulement à cause du "name mangling" (qui n'intervient
pas lorsque l'appel se fait par pointeur) mais aussi parce que
la "calling convention" (Passage des paramètres dans des registres
ou sur la pile ? Dans quel ordre ? Qui fait le ménage sur la pile
au retour - la fonction appelée ou la fonction appelante ? Comment
passer la valeur de retour ?) peut différer entre les deux langages.
Certains compilateurs (par exemple GCC) acceptent la conversion
sans problème (soit ils utilisent la même convention d'appel, soit
ils génèrent un bout de code faisant les conversions nécessaires
s'il en y a besoin) mais cela reste non portable.

(À mon avis, ça serait *Bien* si une nouvelle release de la Norme
C++ mandatait un comportement satisfaisant dans tous les cas...)

Quote:
Mais est-ce possible avec une fonction membre non statique ?

Non.

Il faudrait pouvoir donner dynamiquement l'adresse de la fonction ...
non ?

??

La technique classique la suivante (je détaille pas trop, c'est souvent
posé ici, regarde google pour plus de détails).

extern "C" // pour faire plus beau
Quote:
void threadFct (void* data)
{
MaClasse *mc = static_cast<MaClasse*> data;
mc->MaFonction();
}

int f()
{
static
MaClasse c;
// ...
pthread_create (&th, NULL, &threadFct, &c);
}

Là, il faut faire attention à ce que la durée de vie de l'objet 'c'
ne soit pas plus courte que celle du (de la ?) "thread" crée(e) !
Donc il faudrait déclarer 'c' comme 'static' ou global (attention
alors à la création possible de plusieurs threads qui accèdent
au même objet), ou bien créer un objet dynamique qui ne devra être
détruit qu'une fois quand l[ea] thread en question est terminé(e).

Falk

Back to top
drkm
Guest





PostPosted: Thu Aug 26, 2004 2:48 pm    Post subject: Re: comment déclarer une fonction membre comme fonction call Reply with quote

"Eric Bart" <eb-adm (AT) eric-bart (DOT) pasdepubmerci.net> writes:

Quote:
Il faudrait pouvoir donner dynamiquement l'adresse de la fonction

Si par « dynamiquement » tu entends « à l'exécution », c'est bien le
cas.

--drkm, en recherche d'un stage : http://www.fgeorges.org/ipl/stage.html

Back to top
Eric Bart
Guest





PostPosted: Thu Aug 26, 2004 4:30 pm    Post subject: Re: comment déclarer une fonction membre comme fonction call Reply with quote

Quote:
Mais est-ce possible avec une fonction membre non statique ?

Non.

OK. Merci



Back to top
Eric Bart
Guest





PostPosted: Thu Aug 26, 2004 4:35 pm    Post subject: Re: comment déclarer une fonction membre comme fonction call Reply with quote


"drkm" <usenet.fclcxx (AT) fgeorges (DOT) org> wrote

Quote:
"Eric Bart" <eb-adm (AT) eric-bart (DOT) pasdepubmerci.net> writes:

Il faudrait pouvoir donner dynamiquement l'adresse de la fonction

Si par « dynamiquement » tu entends « à l'exécution », c'est bien le
cas.

Oui c'est ce que je voulais dire.

Mon idée était mauvaise, je pensais pouvoir convertir l'adresse d'une fonction
membre en une adresse de fonction callback. Ca ne doit pas être possible ...



Back to top
drkm
Guest





PostPosted: Thu Aug 26, 2004 6:38 pm    Post subject: Re: comment déclarer une fonction membre comme fonction call Reply with quote

"Eric Bart" <eb-adm (AT) eric-bart (DOT) pasdepubmerci.net> writes:

Quote:
Mon idée était mauvaise, je pensais pouvoir convertir l'adresse
d'une fonction membre en une adresse de fonction callback. Ca ne
doit pas être possible ...

Recherche dans les archives du groupe après quelque chose comme
"extern C callbak foncteur", tu devrais trouver pas mal de solutions.
C'est une question récurrente.

L'idée est que si le pointeur sur fonction doit pointer sur une
fonction extern "C", on n'a pas le choix, on doit créer une fonction
de ce type. Mais elle peut s'arranger pour déléguer à une classe
(fonction membre statique) ou un objet (fonction membre d'instance).

Souvent, les fonctions acceptant des callbacks C acceptent également
un pointeur sur void. On passe alors l'adresse d'un objet. La
fonction destinée à être enregistrée caste alors son argument vers le
type ad-hoc, et appelle la fonction membre ad-hoc de cette objet.

--drkm, en recherche d'un stage : http://www.fgeorges.org/ipl/stage.html

Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Fri Aug 27, 2004 7:37 am    Post subject: Re: comment déclarer une fonction membre comme fonction cal Reply with quote

Falk Tannhäuser <falk.tannhauser (AT) crf (DOT) canon.fr> wrote

Quote:
Loïc Joly wrote:
Eric Bart wrote:

J'aimerais utiliser une fonction membre d'une classe comme une
fonction callback.

Par exemple pour utiliser une thread :
pthread_create (&th, NULL, MaClasse::MaFonction, NULL);

Si MaFonction est déclarée en static, ça fonctionne.

Même ça n'est pas garanti, car à mon avis, pthread_create nécessite
comme argument un pointeur sur une fonction qualifiée 'extern "C"'.

Tout à fait.

Quote:
Les fonctions C++ et C ne sont pas forcement interchangeables entre
elles, non seulement à cause du "name mangling" (qui n'intervient pas
lorsque l'appel se fait par pointeur) mais aussi parce que la "calling
convention" (Passage des paramètres dans des registres ou sur la pile
? Dans quel ordre ? Qui fait le ménage sur la pile au retour - la
fonction appelée ou la fonction appelante ? Comment passer la valeur
de retour ?) peut différer entre les deux langages. Certains
compilateurs (par exemple GCC) acceptent la conversion sans problème
(soit ils utilisent la même convention d'appel, soit ils génèrent un
bout de code faisant les conversions nécessaires s'il en y a besoin)
mais cela reste non portable.

Accepter le code, c'est une extension non conforme, parce que la norme
exige un diagnostique dans ce cas-ci.

Quote:
(À mon avis, ça serait *Bien* si une nouvelle release de la Norme C++
mandatait un comportement satisfaisant dans tous les cas...)

Le problème, c'est que la norme C++ ne peut pas imposer des contraints
sur le C. Le but de l'« extern "Langage" », c'est justement de dire au
compilateur qu'il faut utiliser d'autres conventions. Je ne vois pas
comment la norme C++ pourrait imposer que les conventions soient les
même en C et en C++ -- il ne peut qu'imposer les contraints sur le C++.

Dans la pratique, il faut dire aussi qu'il y a eu des implémentations où
les conventions C et C++ différaient. Ce n'est donc pas qu'une
considération théorique.

--
James Kanze GABI Software http://www.gabi-soft.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

Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Fri Aug 27, 2004 8:20 am    Post subject: Re: comment déclarer une fonction membre comme fonction call Reply with quote

"Eric Bart" <eb-adm (AT) eric-bart (DOT) pasdepubmerci.net> wrote


Quote:
J'aimerais utiliser une fonction membre d'une classe comme une
fonction callback.

Par exemple pour utiliser une thread :
pthread_create (&th, NULL, MaClasse::MaFonction, NULL);

Si MaFonction est déclarée en static, ça fonctionne.

Mais est-ce possible avec une fonction membre non statique ?

Ce n'est pas possible avec une fonction membre, statique ou non. Il faut
que ce soit une fonction libre déclarée « extern "C" ».

Quote:
Il faudrait pouvoir donner dynamiquement l'adresse de la fonction ...
non ?

Il faut en prendre l'adresse, parce que c'est l'adresse d'une fonction
qu'attend pthread_create. Mais où en est le problème :

extern "C"
void*
threadStarter( void* p )
{
return static_cast< MaClass* >( p )->maFonction() ;
}

pthread_create( &th, NULL, &threadStarter, &maThread ) ;

Tiens, une question pour les experts : est-ce qu'une fonction templatée
puisse être « extern "C" » ? Parce que je verais bien un template pour
« threadStarter », ci-dessus.

--
James Kanze GABI Software http://www.gabi-soft.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

Back to top
Jean-Marc Bourguet
Guest





PostPosted: Fri Aug 27, 2004 9:11 am    Post subject: Re: comment déclarer une fonction membre comme fonction call Reply with quote

[email]kanze (AT) gabi-soft (DOT) fr[/email] writes:

Quote:
Tiens, une question pour les experts : est-ce qu'une fonction templatée
puisse être « extern "C" » ? Parce que je verais bien un template pour
« threadStarter », ci-dessus.

como refuse, mais je n'ai pas fait une recherche dans la norme.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Back to top
Falk Tannhäuser
Guest





PostPosted: Fri Aug 27, 2004 10:23 am    Post subject: Re: comment déclarer une fonction membre comme fonction call Reply with quote

[email]kanze (AT) gabi-soft (DOT) fr[/email] wrote:
Quote:
Tiens, une question pour les experts : est-ce qu'une fonction templatée
puisse être « extern "C" » ? Parce que je verais bien un template pour
« threadStarter », ci-dessus.

Je ne sais pas si je suis un expert, mais

____________________________________________________
extern "C" typedef void* pthreadEntryFunc(void*);

template<typename T>
struct wrap_pthreadEntry
{
static pthreadEntryFunc externCfunc;
};

template<typename T>
void* wrap_pthreadEntry<T>::externCfunc(void* p)
{
return static_cast<T*>(p)->MaFonction();
}
_____________________________________________________

est accepté par g++, ainsi que Comeau et Dinkum en ligne (je sais que cela
ne constitue pas une preuve...)

Avec g++, cela me permet de faire
_____________________________________________________
#include <iostream>
#include <ostream>
#include <pthread.h>
#include <cassert>

struct foo
{
foo* MaFonction() { std::cout << "Hello world!" << std::endl; return this; }
};

foo f;

int main()
{
pthread_t thr1;

if(pthread_create(&thr1, NULL, &wrap_pthreadEntry {
std::cerr << "Error during pthtread_create" << std::endl;
return EXIT_FAILURE;
}
void* pthread_return_value = 0;
pthread_join(thr1, &pthread_return_value);
assert(pthread_return_value == &f);
return EXIT_SUCCESS;
}
_____________________________________________________

On pourrait certainement faire quelque chose de plus balèze,
prenant un pointeur sur la fonction membre en paramètre,
puis qui encapsule aussi l'appel à pthread_create, de manière
à empêcher que quelqu'un passe un pointeur sur un type incompatible
comme quatrième argument ...

Falk
Falk

Back to top
Falk Tannhäuser
Guest





PostPosted: Fri Aug 27, 2004 12:03 pm    Post subject: Re: comment déclarer une fonction membre comme fonction call Reply with quote

Falk Tannhäuser wrote:
Quote:
kanze (AT) gabi-soft (DOT) fr wrote:

Tiens, une question pour les experts : est-ce qu'une fonction templatée
puisse être « extern "C" » ? Parce que je verais bien un template pour
« threadStarter », ci-dessus.

Je ne sais pas si je suis un expert, mais
____________________________________________________
extern "C" typedef void* pthreadEntryFunc(void*);

template<typename T
struct wrap_pthreadEntry
{
static pthreadEntryFunc externCfunc;
};

template void* wrap_pthreadEntry {
return static_cast<T*>(p)->MaFonction();
}
_____________________________________________________

est accepté par g++, ainsi que Comeau et Dinkum en ligne (je sais que cela
ne constitue pas une preuve...)

§ 7.5/4 "A C language linkage is ignored for the names of class members
and the member function type of class member functions.functions. [Example:
extern "C" typedef void FUNC_c();
class C {
void mf1(FUNC_c*); // the name of the function mf1 and the member
// function’s type have C++ language linkage; the
// parameter has type pointer to C function
FUNC_c mf2; // the name of the function mf2 and the member
// function’s type have C++ language linkage
static FUNC_c* q; // the name of the data member q has C++ language
// linkage and the data member’s type is pointer to
// C function
};
..."

Donc ce que j'imaginais ne marche pas (au moins sous un compilateur
strictement conforme) :-(


Back to top
Falk Tannhäuser
Guest





PostPosted: Fri Aug 27, 2004 12:44 pm    Post subject: Re: comment déclarer une fonction membre comme fonction call Reply with quote

// Deuxième tentative :

extern "C" typedef void* pthreadEntryFunc(void*);
template<typename T> pthreadEntryFunc threadStarter; // declaration

template<typename T> void* threadStarter( void* p ) // definition
{
return static_cast<T*>( p )->maFonction() ;
}

struct foo
{
foo* maFonction() { std::cout << "Hello world!" << std::endl; return this; }
};

extern "C"
{
void* (*pf)(void*) = 0;
}

void* toto(void* p) { return p; } // extern "C++

int main()
{
pf = &threadStarter // g++ and Dinkum[EDG/C++]
pf = &toto; // Accepted by g++ and Dinkum[VC++/C++], refused (correctly,
// according to the standard) by Comeau and Dinkum[EDG/C++]
return 0;
}
___________________________________________________________________________

Je ne sais pas qui a raison.
Dinkum[VC++/C++] <http://www.dinkumware.com/exam/> me fait

error C2783: 'pthreadEntryFunc threadStarter' : could not deduce template argument for 'T'
error C2563: mismatch in formal parameter list
error C2568: '=' : unable to resolve function overload
could be 'pthreadEntryFunc threadStarter'

Falk
Back to top
James Kanze
Guest





PostPosted: Sat Aug 28, 2004 4:21 pm    Post subject: Re: comment déclarer une fonction membre comme fonction call Reply with quote

Falk Tannhäuser <falk.tannhauser (AT) crf (DOT) canon.fr> writes:

Quote:
kanze (AT) gabi-soft (DOT) fr wrote:
Tiens, une question pour les experts : est-ce qu'une fonction
templatée puisse être « extern "C" » ? Parce que je verais bien un
template pour « threadStarter », ci-dessus.

Je ne sais pas si je suis un expert, mais
____________________________________________________
extern "C" typedef void* pthreadEntryFunc(void*);

template<typename T
struct wrap_pthreadEntry
{
static pthreadEntryFunc externCfunc;
};

template void* wrap_pthreadEntry {
return static_cast<T*>(p)->MaFonction();
}
_____________________________________________________

Tiens, je n'avais pas pensé à la possibilité d'un typedef. La raison
pourquoi une fonction membre statique ne peut pas être « extern "C" »
est simple : il n'y a pas de syntaxe pour dire qu'elle est « extern
"C" ». Il n'y a rien de fondamental qui l'interdit.

N'empêche que je crois que c'est une question pour comp.std.c++ ?

Seulement une question : comment est-ce que tu fais pour définir la
fonction. (Si je me rappelle bien, tu n'as pas droit au typedef dans la
définition.)

Quote:
est accepté par g++, ainsi que Comeau et Dinkum en ligne (je sais
que cela ne constitue pas une preuve...)

G++, en tout cas, ne traite pas le « extern "C" » comme faisant partie
du type.

À vrai dire, il faudrait avoir un compilateur où les conventions d'appel
était réelement différentes entre les deux langages, pour voir ce que ça
donne à l'exécution.

--
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

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (French) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.