OVH Cloud OVH Cloud

comment déclarer une fonction membre comme fonction callback ?

13 réponses
Avatar
Eric Bart
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

3 réponses

1 2
Avatar
Falk Tannhäuser
Falk Tannhäuser wrote:
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<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...)


§ 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) :-(


Avatar
Falk Tannhäuser
// 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<foo>; // Refused by Dinkum[VC++/C++], accepted by
// 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
Avatar
James Kanze
Falk Tannhäuser writes:

|> 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<typename T>
|> void* wrap_pthreadEntry<T>::externCfunc(void* p)
|> {
|> 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.)

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