[Visual C++] Problème avec _beginthread... [Allons plus loin]

Problème avec _beginthread... [Allons plus loin] [Visual C++] - C++ - Programmation

Marsh Posté le 27-05-2002 à 17:39:12    

Salut,
Je me heurte actuellement à un problème avec la fonction _beginthread :
 
class CMaClasse
{
public:
 void FonctionAppelant(void* args);
private:
 void FonctionAppelee(void* arg);
};
 
void CMaClasse::FonctionAppelant(void* args)
{
_beginthread(FonctionAppelee,0,(void*)a); //la y a un problème
}
 
 
void CMaClasse::FonctionAppelee(void* arg)
{
 //...
}
 
Le compilo de Visual C++ me sort ça comme erreur :
[...] error C2664: '_beginthread' : cannot convert parameter 1 from 'void (void *)' to 'void (__cdecl *)(void *)'
 
Peut-on m'aider ?
Merci
 ANT

 

[jfdsdjhfuetppo]--Message édité par antsite le 28-05-2002 à 17:17:51--[/jfdsdjhfuetppo]

Reply

Marsh Posté le 27-05-2002 à 17:39:12   

Reply

Marsh Posté le 27-05-2002 à 18:18:41    

je suis pas sur que ça soit la solution mais en tout cas, les fonctions de thread doivent être déclarées en static .

Reply

Marsh Posté le 27-05-2002 à 18:52:44    

C'est possible, en tout cas quand je déclare la fonction appelée normalement, pas dans une classe, il n'y a aucun problème. Alors comment faire pour qu'elle soit acceptée lorsqu'elle fait partie d'une classe ?
 
Sinon j'ai un autre problème concernant les arguments à passer à la fonction appelée. Je souhaite en passer 2, comment faire ? 1 pas de problème, mais 2... est-on obligé de passer par une structure contenant les arguments ?

Reply

Marsh Posté le 27-05-2002 à 19:48:03    

t'as essayé en mettant ta fcn en static ?

Reply

Marsh Posté le 27-05-2002 à 19:54:00    

Oui à l'instant, ça marche, merci beaucoup  :jap:  
Reste le problème des arguments, si tu m'aider...
thx

Reply

Marsh Posté le 27-05-2002 à 20:10:27    

:hello:  
 
essaie ceci :

Citation :


class CMaClasse  
{  
public:  
void FonctionAppelant(void* args);  
private:  
void __cdecl FonctionAppelee(void* arg);  
};  
 
void CMaClasse::FonctionAppelant(void* args)  
{  
_beginthread(FonctionAppelee,0,(void*)a); //la y a un problème  
}  
 
 
void __cdecl CMaClasse::FonctionAppelee(void* arg)  
{  
//...  
}


 
A+ mon ex-boolay  :D

 

[jfdsdjhfuetppo]--Message édité par Harkonnen le 27-05-2002 à 20:11:22--[/jfdsdjhfuetppo]


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 27-05-2002 à 20:12:14    

Merci Harkonnen mais le fait de mettre static devant la fonction dans la classe résout le problème  :hello:  
Mais je suis toujours embeté avec ces 2 arguments de type différent :
 
Voici mon code de passage de 2 arguments (de type différent !) :
 
void *arg[2];
 
arg[0] = pDialog;
arg[1] = (void*)n;
_beginthread(FonctionAppelee,0,arg);
 
pour l'instant, pas de problème, c'est pour les récupérer que je bloque :
en effet la fonction lancée en thread doit impérativement prendre (void* arg) comme param.
Donc comment reprendre les 2 arguments passés via ce void* arg ?

Reply

Marsh Posté le 27-05-2002 à 20:53:50    

Le problème de départ (__cdecl) n'est pas totalement résolu :
mettre static résoud le problème mais je ne peux plus dans la fonction static modifier ma classe :
 illegal reference to data member 'CMaClasse::membre' in a static member function
 
Donc j'ai pris la solution à Harkonnen qui fonctionne très bien :
mettre __cdecl lors de la déclaration dans la classe ainsi que lors de la définition de la fonction (cf ci-dessus).
Mais je ne peux pas imbriquer 2 fonctions __cdecl, y a toujours la même erreur (début du topic), je m'explique :
 
class CMaClasse
{
public:
void __cdecl FonctionAppelant(void* args);
 
private:
void __cdecl FonctionAppelee(void* arg);
};
 
void __cdecl CMaClasse::FonctionAppelant(void* args)
{
_beginthread(FonctionAppelee,0,(void*)a); //la y a toujours un problème !
}
 
 
void __cdecl CMaClasse::FonctionAppelee(void* arg)
{
//...
}
 
void CUneAutreClasse::OnButton1(void)
{
 CMaClasse test;
 
 _beginthread(FonctionAppelant,0,this); //la aucun problème
}
 
donc le premier _beginthread (une autre classe appelle), il n'y a aucun pb. Mais la fonction qui vient d'être appelée doit appeler à son tour une autre fonction et la l'erreur resurgit même avec __cdecl.
Donc une fonction, pas de problème (soit static, soit __cdecl), mais après... Pas facile ces 2 threads imbriqués !
 
P.S : et puis y a toujours le problème des arguments, enfin chaque chose en son temps !

Reply

Marsh Posté le 27-05-2002 à 21:04:40    

pour les arguments, faut que tu castes tes arguments (enfin, moi, c'est comme ça que je ferais) :
 
tu as  
   void *arg[2];  
   arg[0] = pDialog;  
   arg[1] = (void*)n;  
   _beginthread(FonctionAppelee,0,arg);  
 
dans ton thread, tu fais ensuite
 
CDialog *pDialog = (CDialog*)arg[0];
void *n = (void*)arg[1];
 
et voilà comment tu récupères tes arguments ! enfin, je pense...

Reply

Marsh Posté le 27-05-2002 à 21:10:16    

Citation :

Donc une fonction, pas de problème (soit static, soit __cdecl), mais après


 
Il y a plusieurs conventions d'appels.
Les membres d'un classe sont par défaut thiscall, et sinon c'est __cdecl.
Une fonction static n'est pas une véritable fonction membre, elle est donc __cdecl.
 
Pour les paramètres, le mieux est de créer ton propre type (une structure que tu définis dans ta classe) et de passer un pointeur sur une variable de ce type.


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 27-05-2002 à 21:10:16   

Reply

Marsh Posté le 27-05-2002 à 21:34:33    

Pour les paramètres voila l'erreur (même avec un cast)
 
cannot convert parameter 3 from 'CMaClasse::ARGS' to 'void *'
 
mais je ne sais toujours pas comment faire avec mes 2 _beginthread  :sweat:  :sweat:  :sweat:  
 
ca me prends la tête...............

Reply

Marsh Posté le 27-05-2002 à 22:13:13    

antsite a écrit a écrit :

Salut,
Je me heurte actuellement à un problème avec la fonction _beginthread :
 
class CMaClasse
{
public:
 void FonctionAppelant(void* args);
private:
 void FonctionAppelee(void* arg);
};
 
void CMaClasse::FonctionAppelant(void* args)
{
_beginthread(FonctionAppelee,0,(void*)a); //la y a un problème
}
 
 
void CMaClasse::FonctionAppelee(void* arg)
{
 //...
}
 
Le compilo de Visual C++ me sort ça comme erreur :
[...] error C2664: '_beginthread' : cannot convert parameter 1 from 'void (void *)' to 'void (__cdecl *)(void *)'
 
Peut-on m'aider ?
Merci
 ANT  
 
 




 
Salut, ton probleme c que tu utilise des classes et tu n'as pas le droit de faire ca... je le sais j'ai eu le meme probleme.
La seule solution est d'utilisé les classes thread de la MFC (classe CWinThread) ou alors tu galère a faire des fonctions en c static et tu t'amuse avec les pointeurs sur fonctions mais la c tres crade...
 
En esperant avoir repondu a ta question...
@+

Reply

Marsh Posté le 28-05-2002 à 13:39:05    

Ok donc je ne vais pas déclarer ces fonctions dans des classes.
merci

Reply

Marsh Posté le 28-05-2002 à 17:18:12    

Cela se révèle donc difficile d'utiliser des fonctions membres d'une classe avec _beginthread. Donc je vais devoir les déclarer en tant que 'simples' fonctions :
 
void FonctionAppelant(void* pDialog);
void FonctionAppelee(void* pDialog);
 
class CMaClasse
{
public:
static int var;
bool var2;
};
 
Seulement que faire du reste de la classe, car cette classe ne présente désormais plus grand intérêt si ces 2 fonctions n'en font pas partie. J'ai dans la classe 2 autres membres, dont un en static.
Dois-je déclarer en variables globales les 2 membres ou les laisser dans la classe où ils seront les 2 seuls membres ? Je vous serais reconnaissant si vous pouviez me proposer un schéma propre d'architecture de mon application, merci.
 
Une autre question mois importante, pour les arguments, comment faire pour déclarer et définir la struct à utiliser : déclaration & définition dans la classe, ou seulement déclaration, ou l'inverse ?

Reply

Marsh Posté le 28-05-2002 à 18:51:19    

Ba la c sur ta classe elle va plus servir a grand chose...
 
le truc c que tu fait une classe thread declarer en gros comme ca :
 
class C_MyThread : public CWinThread
{
  public:
    C_MyThread(void);
    virtual ~C_MyThread(void);
// et tu rajoute tes fonctions si besoin
}
 
et tu fabrique une autre classe qui elle appellera ta classe thread de la facon suivante :
 
...
thread1 = (C_MyThread *) AfxBeginThread(RUNTIME_CLASS(C_MyThread), THREAD_PRIORITY_NORMAL, 0, 0x4);
thread1->ResumeThread();
...
 
si tu veux plus de precision sur les parametres de AfxBeginThread regarde dans les MSDN.

Reply

Marsh Posté le 28-05-2002 à 23:30:47    

Si tu veux réinventer la roue:
Il ya des bouts de code un peu vilain ( pour la la terminaison du thread) mais ça fonctionne.
 
DECLARATION
class CThread  
{
public:
 void PostMessage(UINT message);
 BOOL GetMessage(UINT message);
 
 void Resume(void);
 void Suspend(void);
   virtual void Terminate(void);
 
 CDAQThread();
 virtual ~CDAQThread();
 
protected:
 
 virtual void Quit(void);
 virtual void Run(void);
 virtual void Init(void);
 
   virtual  BOOL GetMessage(MSG*);
 virtual void PostMessage(MSG* pMsg);
 
private:
   HANDLE m_hThread;
   DWORD  m_dwThreadId;
 
private:
 static void Thread(LPVOID lpvParameter);
};
 
IMPLEMENTATION:
 
CThread  ::CThread  ()
{
   m_hThread = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CDAQThread::Thread, (LPVOID)this, CREATE_SUSPENDED , &m_dwThreadId );
}
 
CThread  ::~CThread  ()
{
 
}
 
 
void CThread  ::Init()
{
 
}
 
void CThread  ::Run()
{
 
}
 
void CThread  ::Quit()
{
 
}
 
void CThread  ::Suspend()
{
   if(m_hThread)
      ::SuspendThread(m_hThread);
}
 
void CThread  ::Resume()
{
   if(m_hThread)
      ::ResumeThread(m_hThread);
}
 
void CThread  ::Thread(LPVOID lpvParameter)
{
   CDAQThread* pDAQThread=(CDAQThread*)lpvParameter;
 
   pDAQThread->Init();
   pDAQThread->Run();
   pDAQThread->Quit();
}
 
void CThread  ::PostMessage(MSG* pMsg)
{
   if(pMsg)
      ::PostThreadMessage(m_dwThreadId,pMsg->message,pMsg->wParam,pMsg->lParam);
}
 
BOOL CThread  ::GetMessage(MSG* pMsg)
{
   return ::GetMessage(pMsg,NULL,0,0);
}
 
BOOL CThread  ::GetMessage(UINT message)
{
   MSG msg;
   return ::GetMessage(&msg,NULL,message,message);
}
 
void CThread  ::Terminate()
{
   if(m_hThread)
      ::TerminateThread(m_hThread,0);
 
   DWORD dwExitCode;
   DWORD dwTimeout=DAQTHREAD_TIMEOUT;
 
   while(GetExitCodeThread(m_hThread,&dwExitCode) &&  dwExitCode==STILL_ACTIVE){
      Sleep(100);
      if(!(dwTimeout--)) return;
   }
 
   ::CloseHandle(m_hThread);
}
 
void CThread  ::PostMessage(UINT message)
{
   ::PostThreadMessage(m_dwThreadId,message,0,0);
}


---------------
... [:phlb]
Reply

Marsh Posté le 30-05-2002 à 17:33:48    

phlb a écrit a écrit :

void CThread  ::Terminate()
{
   if(m_hThread)
      ::TerminateThread(m_hThread,0);
(...)




attention avec TerminateThread... c'est une fonction très peu sécurisée !
voir MSDN pour tous les saccages provoqués par cette fonction !


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed