Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

C++, pointeurs de fonctions, fonctions membres, threads et signaux

39 réponses
Avatar
vincent.lecoq
Je cherche a develloper une petite librairie en C++ sous Linux (et/ou
BSD ).
Elle a besoin des appels systeme signal et pthread_create.
La fonction associee a mon signal est un membre d'une des classes de
ma librairie, elles est appelee en interne par celle ci pour detacher
un process puis restaurer l'environement d'origine. or g++ (et le C++
en general) m'interdisent de passer cette fonction a signal car elle
est du type MaClasse::ma_fonction et comme cette fonction doit se
servir de certaines variables propres a l'instance de la classe
appelante, je ne peux par l'exterioriser ...

Comment faire ?

10 réponses

1 2 3 4
Avatar
Fabien LE LEZ
Si je ne m'abuse, c'est la question habituelle, qui appelle les
réponses habituelles. Cf donc Google :
<http://www.google.com/groups?hl=en&lr=&ie=UTF-8&q=Pointeurs+de+fonctions+membres+group%3Afr.comp.lang.c%2B%2B&btnG=Search>


--
schtroumpf schtroumpf
Avatar
Serge Paccalin
Le vendredi 2 juillet 2004 à 11:02, LECOQ Vincent a écrit dans
fr.comp.lang.c++ :

Je cherche a develloper une petite librairie en C++ sous Linux (et/ou
BSD ).
Elle a besoin des appels systeme signal et pthread_create.
La fonction associee a mon signal est un membre d'une des classes de
ma librairie, elles est appelee en interne par celle ci pour detacher
un process puis restaurer l'environement d'origine. or g++ (et le C++
en general) m'interdisent de passer cette fonction a signal car elle
est du type MaClasse::ma_fonction et comme cette fonction doit se
servir de certaines variables propres a l'instance de la classe
appelante, je ne peux par l'exterioriser ...

Comment faire ?


Comme pthread_create() accepte, en plus du pointeur vers la fonction, un
pointeur vers une donnée utilisateur (généralement un void *) qui sera
passé à la fonction, il y a une solution.

Tu déclare une fonction membre statique avec le format attendu par
pthread_create(), et une autre fonction membre sans l'argument void * :

class LaClasse
{
static void *StartStatic(void *pUser);
void *Start();
}

void *LaClasse::StartStatic(void *pUser)
{
LaClasse *pThis = (LaClasse *)pUser;
return pThis->Start();
}

void *LaClasse::Start()
{
// ici, ton vrai code utile de thread
}

Ensuite, tu appelles pthread_create() avec la fonction membre statique
et un pointeur vers l'objet :

LaClasse MonObjet;
pthread_create(pThread,pAttr,LaClasse::StartStatic,&MonObjet);

La fonction membre void *LaClasse::Start() n'est pas indispensable, mais
ça évite de trimballer des "pThis->"...

Je te laisse mettre des casts plus propres.

--
___________ 2004-07-02 12:11:51
_/ _ _`_`_`_) Serge PACCALIN -- sp ad mailclub.net
_L_) Il faut donc que les hommes commencent
-'(__) par n'être pas fanatiques pour mériter
_/___(_) la tolérance. -- Voltaire, 1763

Avatar
Serge Paccalin
Le vendredi 2 juillet 2004 à 11:02, LECOQ Vincent a écrit dans
fr.comp.lang.c++ :

Je cherche a develloper une petite librairie en C++ sous Linux (et/ou
BSD ).
Elle a besoin des appels systeme signal et pthread_create.
La fonction associee a mon signal est un membre d'une des classes de
ma librairie, elles est appelee en interne par celle ci pour detacher
un process puis restaurer l'environement d'origine. or g++ (et le C++
en general) m'interdisent de passer cette fonction a signal car elle
est du type MaClasse::ma_fonction et comme cette fonction doit se
servir de certaines variables propres a l'instance de la classe
appelante, je ne peux par l'exterioriser ...

Comment faire ?


Comme pthread_create() accepte, en plus du pointeur vers la fonction, un
pointeur vers une donnée utilisateur (généralement un void *) qui sera
passé à la fonction, il y a une solution.

Tu déclare une fonction membre statique avec le format attendu par
pthread_create(), et une autre fonction membre sans l'argument void * :

class LaClasse
{
static void *StartStatic(void *pUser);
void *Start();
}

void *LaClasse::StartStatic(void *pUser)
{
LaClasse *pThis = (LaClasse *)pUser;
return pThis->Start();
}

void *LaClasse::Start()
{
// ici, ton vrai code utile de thread
}

Ensuite, tu appelles pthread_create() avec la fonction membre statique
et un pointeur vers l'objet :

LaClasse MonObjet;
pthread_create(pThread,pAttr,LaClasse::StartStatic,(void *)&MonObjet);

La fonction membre void *LaClasse::Start() n'est pas indispensable, mais
ça évite de trimballer des "pThis->"...

Je te laisse mettre des casts plus propres et le contrôle d'erreur.

--
___________ 2004-07-02 12:11:51
_/ _ _`_`_`_) Serge PACCALIN -- sp ad mailclub.net
_L_) Il faut donc que les hommes commencent
-'(__) par n'être pas fanatiques pour mériter
_/___(_) la tolérance. -- Voltaire, 1763

Avatar
Franck Branjonneau
Serge Paccalin écrivait:

Le vendredi 2 juillet 2004 à 11:02, LECOQ Vincent a écrit dans
fr.comp.lang.c++ :

Je cherche a develloper une petite librairie en C++ sous Linux (et/ou
BSD ).
Elle a besoin des appels systeme signal et pthread_create.
La fonction associee a mon signal est un membre d'une des classes de
ma librairie, elles est appelee en interne par celle ci pour detacher
un process puis restaurer l'environement d'origine. or g++ (et le C++
en general) m'interdisent de passer cette fonction a signal car elle
est du type MaClasse::ma_fonction et comme cette fonction doit se
servir de certaines variables propres a l'instance de la classe
appelante, je ne peux par l'exterioriser ...

Comment faire ?


Comme pthread_create() accepte, en plus du pointeur vers la fonction, un
pointeur vers une donnée utilisateur (généralement un void *) qui sera
passé à la fonction, il y a une solution.

[ La solution erronée.]


pthread_create() veut une fonction "C" pure. Il faut en plus

extern "C" {

void *CStartStatic(void *pUser);

}

qui appelle LaClasse::StartStatic().
--
Franck Branjonneau


Avatar
drkm
Serge Paccalin writes:

class LaClasse
{
static void *StartStatic(void *pUser);
void *Start();
}

void *LaClasse::StartStatic(void *pUser)
{
LaClasse *pThis = (LaClasse *)pUser;
return pThis->Start();
}

void *LaClasse::Start()
{
// ici, ton vrai code utile de thread
}


Même s'il s'agit de la solution souvent présentée, et qui devrait
fonctionner partout, cela n'est pas garanti par la norme, il me
semble. Un pointeur vers une fonction membre statique n'est pas de
même type qu'un pointeur vers une fonction libre. Je pense que la
solution correcte est :

class LaClasse {
void * start() {
// ...
}
} ;

extern "C" {
void * LaClasseStartCallback( void * obj ) {
LaClasse * c = static_cast< LaClasse * >( obj ) ;
return c->start() ;
}
}

--drkm

Avatar
drkm
Franck Branjonneau writes:

Serge Paccalin écrivait:

Comme pthread_create() accepte, en plus du pointeur vers la fonction, un
pointeur vers une donnée utilisateur (généralement un void *) qui sera
passé à la fonction, il y a une solution.

[ La solution erronée.]


pthread_create() veut une fonction "C" pure. Il faut en plus

extern "C" {

void *CStartStatic(void *pUser);

}

qui appelle LaClasse::StartStatic().


... qui ne sert plus alors à rien. CStartStatic() peut elle-même
faire le boulot de LaClasse::StartStatic(), qui n'a plus de raison
d'être :

extern "C"
{
void * CStartStatic( void * pUser )
{
LaClasse * c = static_cast< LaClasse * >( pUser ) ;
return c->Start() ;
}
}

--drkm


Avatar
Serge Paccalin
Le vendredi 2 juillet 2004 à 13:40, Franck Branjonneau a écrit dans
fr.comp.lang.c++ :

Serge Paccalin écrivait:

Le vendredi 2 juillet 2004 à 11:02, LECOQ Vincent a écrit dans
fr.comp.lang.c++ :

Je cherche a develloper une petite librairie en C++ sous Linux (et/ou
BSD ).
Elle a besoin des appels systeme signal et pthread_create.
La fonction associee a mon signal est un membre d'une des classes de
ma librairie, elles est appelee en interne par celle ci pour detacher
un process puis restaurer l'environement d'origine. or g++ (et le C++
en general) m'interdisent de passer cette fonction a signal car elle
est du type MaClasse::ma_fonction et comme cette fonction doit se
servir de certaines variables propres a l'instance de la classe
appelante, je ne peux par l'exterioriser ...

Comment faire ?


Comme pthread_create() accepte, en plus du pointeur vers la fonction, un
pointeur vers une donnée utilisateur (généralement un void *) qui sera
passé à la fonction, il y a une solution.

[ La solution erronée.]


pthread_create() veut une fonction "C" pure. Il faut en plus

extern "C" {

void *CStartStatic(void *pUser);

}

qui appelle LaClasse::StartStatic().


Dans ce cas, autant court-circuiter StartStatic() et appeler directement
pThis->Start() dans CStartStatic.

Il n'y a vraiment pas moyen de déclarer une méthode statique avec les
bons attributs (on parle de gcc, là, j'imagine ?) pour la faire accepter
par pthread_create() ?

--
___________ 2004-07-02 15:38:54
_/ _ _`_`_`_) Serge PACCALIN -- sp ad mailclub.net
_L_) Il faut donc que les hommes commencent
-'(__) par n'être pas fanatiques pour mériter
_/___(_) la tolérance. -- Voltaire, 1763



Avatar
drkm
Serge Paccalin writes:

Il n'y a vraiment pas moyen de déclarer une méthode statique avec les
bons attributs (on parle de gcc, là, j'imagine ?)


Ben, heu, non. De C++.

--drkm

Avatar
Serge Paccalin
Le vendredi 2 juillet 2004 à 16:08, drkm a écrit dans fr.comp.lang.c++ :

Serge Paccalin writes:

Il n'y a vraiment pas moyen de déclarer une méthode statique avec les
bons attributs (on parle de gcc, là, j'imagine ?)


Ben, heu, non. De C++.


Ce que je voulais dire par là, c'est : « N'y aurait-il pas une solution
spécifique à un compilateur (un mot-clef non-standard) permettant
de... ? » Et comme la question d'origine parle de Linux, le compilateur
utilisé est probablement gcc (enfin, g++).

--
___________ 2004-07-02 17:43:08
_/ _ _`_`_`_) Serge PACCALIN -- sp ad mailclub.net
_L_) Il faut donc que les hommes commencent
-'(__) par n'être pas fanatiques pour mériter
_/___(_) la tolérance. -- Voltaire, 1763


Avatar
darkman_spam
Serge Paccalin wrote in message news:...

Le vendredi 2 juillet 2004 à 16:08, drkm a écrit dans fr.comp.lang.c++ :

Serge Paccalin writes:

Il n'y a vraiment pas moyen de déclarer une méthode statique avec les
bons attributs (on parle de gcc, là, j'imagine ?)


Ben, heu, non. De C++.


Ce que je voulais dire par là, c'est : « N'y aurait-il pas une solution
spécifique à un compilateur (un mot-clef non-standard) permettant
de... ? »


Mais il existe une solution standard. Maintenant, si tu es prêt à
sacrifier la portabilité afin d'avoir une fonction membre plutôt
qu'une fonction libre, ce dont je ne vois pas l'intérêt, il se peut en
effet que cela soit supporté par ton compilateur. Mais il faut alors
lui demander à lui, pas à nous.

--drkm



1 2 3 4