IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage C++ Discussion :

Comme Appeler une fonction CALLBACK dans une classe


Sujet :

Langage C++

  1. #1
    Membre à l'essai
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Novembre 2012
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Novembre 2012
    Messages : 15
    Points : 10
    Points
    10
    Par défaut Comme Appeler une fonction CALLBACK dans une classe
    Bonjour,

    j'ai développé une DLL qui me permet de faire appel à des fonctions d'un DLL spécialisée dans le traitement audio (bass.dll). La première version de ma DLL fonction correctement mais ne fait pas appel à des classes. Notamment l'appel à la fonction Callback depuis la fonction SynchroPlaylist

    Maintenant, je souhaite faire évoluer ma DLL et créer une classe Play_list. Tout semble Ok à l'exception du passage en paramètre de la fonction Callback dans la fonction SynchroPlaylist. J'ai bien lu dans certains forum que la technique à mettre en oeuvre est particulière mais mon niveau en C++ et POO ne m'a pas permis de saisir toutes les subtilités.

    Afin que vous puissiez m'aider à trouver une solution je vous joins le code en question en question. En fait, je ne sais pas :
    - quelle syntaxe utiliser pour faire l'appel de la callback et passer le paramètre à la fonction appelante.
    - si un fonction callback peut faire partie d'une classe.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
     
    #include "stdafx.h"
    #include "bass.h"
    #include "bassmix.h"
    #include <sstream> 
    #include <string>  
    #include <iostream>
    #include <random>
    #include <time.h>
     
     
    class Play_list {
     
    private:
    	int rand_a_b(int a, int b);
    	int* init_tableau(int a, int b);
    	void melanger(int* tableau, int taille);
    	std::string new_file_audio(std::string P_playlist, char P_separateur);
    	void CALLBACK SyncProc(HSYNC handle, DWORD channel, DWORD data, void *user);
     
    	std::string m_liste_fichier_audio;
    	int m_nombre_fichier_audio; // Nombre total de fichiers audio dans la play list
    	int* m_tab_playlist; // Tableau d'ordre de lecture de la playlist
    	int cpt_tab; // Position interne de parcours de la playlist
     
    public:
    	void SynchroPlaylist(DWORD P_HDMixer, DWORD P_Flags, QWORD P_Param, DWORD P_Nb_File_audio, const char *P_PlayList, DWORD P_len_char, BOOL P_Lect_alea);
    	int m_position_actuelle; // Position actuelle de lecture dans le tableau	
     
    	DWORD m_mixer;
    	DWORD m_source;
     
    };
     
    ....
    .....
     
    // FUNCTION DE CALLBACK SPECIFIQUE BASS
    //-------------------------------------
    void CALLBACK Play_list::SyncProc(HSYNC handle, DWORD channel, DWORD data, void *user)
    {
    	HSTREAM l_next_stream=0;
    	BOOL L_Return;
     
    	std::string l_fic_audio = new_file_audio(m_liste_fichier_audio,';');
     
    	l_next_stream = BASS_StreamCreateFile(false,l_fic_audio.c_str(),0,0,BASS_STREAM_DECODE|BASS_SAMPLE_FLOAT);
    	L_Return = BASS_Mixer_StreamAddChannel(m_mixer, l_next_stream, BASS_STREAM_AUTOFREE|BASS_MIXER_NORAMPIN);
    	L_Return = BASS_ChannelSetPosition(m_mixer,0,BASS_POS_BYTE);
    }
     
    void Play_list::SynchroPlaylist(DWORD P_HDMixer, DWORD P_Flags, QWORD P_Param, DWORD P_Nb_File_audio, const char *P_PlayList, DWORD P_len_char, BOOL P_Lect_alea)
    {
     
    	srand(time(NULL));
    	m_liste_fichier_audio = P_PlayList;
    	m_nombre_fichier_audio = P_Nb_File_audio;
    	m_tab_playlist=init_tableau(1,P_Nb_File_audio);
     
    	...
     
    	std::string First_Fic_Audio = new_file_audio(m_liste_fichier_audio,';');
     
    	m_mixer = BASS_Mixer_StreamCreate(44100,2,BASS_MIXER_END);
     
    	BASS_ChannelSetSync(m_mixer,BASS_SYNC_END|BASS_SYNC_MIXTIME,0,Play_list::SyncProc,0);
     
    	m_source = BASS_StreamCreateFile(false,First_Fic_Audio.c_str(),0,0,BASS_STREAM_DECODE|BASS_SAMPLE_FLOAT);  //1st file open	
    	BASS_Mixer_StreamAddChannel(m_mixer,m_source,BASS_STREAM_AUTOFREE);
     
    }
    Même si je retire Play_list:: devant SynProc dans le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    BASS_ChannelSetSync(m_mixer,BASS_SYNC_END|BASS_SYNC_MIXTIME,0,Play_list::SyncProc,0);
    une erreur est générée par le compilateur (qui est VS 2012)

    Par avance merci de vos retours et de votre aide
    Cordialement
    Fabien

  2. #2
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    On veut bien t'aider, mais... quel est le message d'erreur?

    ca ne serait pas "il manque un &"?

    essaie BASS_ChannelSetSync(m_mixer,BASS_SYNC_END|BASS_SYNC_MIXTIME,0,&Play_list::SyncProc,0);
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  3. #3
    Membre à l'essai
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Novembre 2012
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Novembre 2012
    Messages : 15
    Points : 10
    Points
    10
    Par défaut
    Citation Envoyé par leternel Voir le message
    On veut bien t'aider, mais... quel est le message d'erreur?

    ca ne serait pas "il manque un &"?

    essaie BASS_ChannelSetSync(m_mixer,BASS_SYNC_END|BASS_SYNC_MIXTIME,0,&Play_list::SyncProc,0);
    Tu as raison, je vais préciser les messages d'erreur retournés par la compilateur.
    Pour le & j'avais déjà fais l'essai, ça ne convient pas. Voici :

    BASS_ChannelSetSync(m_mixer,BASS_SYNC_END|BASS_SYNC_MIXTIME,0,&Play_list::SyncProc,0);Message d'erreur : error C2664: 'BASS_ChannelSetSync' : impossible de convertir le paramètre 4 de 'void (__stdcall Play_list::* ) (.....)' en 'SYNCPROC (__stdcall *)'

    BASS_ChannelSetSync(m_mixer,BASS_SYNC_END|BASS_SYNC_MIXTIME,0,&SyncProc,0);Message d'erreur : error C2276: '&' : opération non conforme sur l'expression d'une fonction membre.

    BASS_ChannelSetSync(m_mixer,BASS_SYNC_END|BASS_SYNC_MIXTIME,0,SyncProc,0);Message d'erreur : error C3867: &'Play_list::SyncProc' : liste d'arguments manquante dans l'appel de fonction ; utilisez 'Play_list::SyncProc' pour créer un pointeur vers membre.

    Je n'arrive pas à trouver la bonne syntaxe. Par contre, j'ai lu dans un billet sur internet que le fait qu'une fonction soit static ou non pouvait jouer. Qu'en passez-vous?
    Sans aucune certitude, je vais poursuivre mes investigations dans cette direction.

    Cordialement.

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 629
    Points : 10 554
    Points
    10 554
    Par défaut
    Non testé , mais

    Soit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Play_list {
    // ...
     
        typedef void (Play_list::* FUNC_PTR) (DWORD, DWORD, QWORD, DWORD, const char*, DWORD, BOOL);
     
    // ...
     
        void CALLBACK SyncProc(HSYNC handle, DWORD channel, FUNC_PTR data, void *user);
     
    // ...
     
    };

    Soit avec avec un cast, mais cela ne va pas marcher parce que ton pointeur va être tronqué en DWORD
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    BASS_ChannelSetSync(m_mixer, BASS_SYNC_END | BASS_SYNC_MIXTIME, 0, (DWORD) &Play_list::SyncProc, 0);

  5. #5
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Citation Envoyé par flesenne Voir le message
    BASS_ChannelSetSync(m_mixer,BASS_SYNC_END|BASS_SYNC_MIXTIME,0,&Play_list::SyncProc,0);;
    Message d'erreur : error C2664: 'BASS_ChannelSetSync' : impossible de convertir le paramètre 4 de 'void (__stdcall Play_list::* ) (.....)' en 'SYNCPROC (__stdcall *)'

    BASS_ChannelSetSync(m_mixer,BASS_SYNC_END|BASS_SYNC_MIXTIME,0,&SyncProc,0);.
    Message d'erreur : error C2276: '&' : opération non conforme sur l'expression d'une fonction membre.

    BASS_ChannelSetSync(m_mixer,BASS_SYNC_END|BASS_SYNC_MIXTIME,0,SyncProc,0);.
    Message d'erreur : error C3867: &'Play_list::SyncProc' : liste d'arguments manquante dans l'appel de fonction ; utilisez 'Play_list::SyncProc' pour créer un pointeur vers membre.
    Dans les cas 2 et 3, c'est de la syntaxe, le compilateur te dit, en résumé, que tu exprimes mal un pointeur de fonction membre.

    Cas 1: impossible de convertir le paramètre 4 de 'void (__stdcall Play_list::* ) (.....)' en 'SYNCPROC (__stdcall *)'
    Ca, c'est la vrai faute: relative au sens.
    Impossible de convertir un "pointeur de fonction membre de Play_list retournant void" en pointeur de fonction libre retournant SYNCPROC.
    La seule solution, de fournir un pointeur de fonction libre, ou de changer la fonction BASS_ChannelSetSync.

    Une fonction static vaut une fonction libre, car la classe/structure ne lui sert que de namespace (et de privauté)
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Je suis sûr que c'est quelque part dans la FAQ, mais bon:

    Le prototype de tes fonctions callback contient un void* user, c'est précisément ce dont tu as besoin:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    typedef int (*FONCTION_CALLBACK)(int param1, int param2, void* user)
     
    void FonctionQuiPrendUnCallback(char const *param1, FONCTION_CALLBACK pCallback, void * user);
     
    class MaClasse
    {
    	int MonCallback(int param1, int param2)
    	{
    		//blabla
    	}
    public:
    	static int SMonCallback(int param1, int param2, void* user)
    	{
    		MaClasse * pObj = static_cast< MaClasse * >(user);
    		return pObj->MonCallback(param1, param2);
    	}
    };
     
    ...
     
    int main(void)
    {
    	MaClasse obj;
    	FonctionQuiPrendUnCallback("toto", MaClasse:SMonCallback, &obj);
    }
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Membre à l'essai
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Novembre 2012
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Novembre 2012
    Messages : 15
    Points : 10
    Points
    10
    Par défaut
    Merci à tous pour vos retours.
    Ils m'ont permis de trouver la solution. Pour info, c'est la solution exposée par Médinoc qui était la réponse à ma problématique. Il faut effectivement passer this dans le paramètre "void* user" de la callback et adapter le contenu de la fonction.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 3
    Dernier message: 02/07/2013, 20h49
  2. appeler une fonction php dans une fonction javaScript
    Par geeksDeve dans le forum Langage
    Réponses: 3
    Dernier message: 17/04/2012, 15h30
  3. Réponses: 8
    Dernier message: 05/04/2011, 08h06
  4. Réponses: 10
    Dernier message: 14/03/2009, 13h36
  5. Réponses: 1
    Dernier message: 25/10/2007, 21h25

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo