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

C++/CLI Discussion :

Parser des commandes (recv) proprement/efficacement ?


Sujet :

C++/CLI

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    162
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 162
    Points : 62
    Points
    62
    Par défaut Parser des commandes (recv) proprement/efficacement ?
    Bonjour, je me permet de poster cette question, j'ai créer un petit programme client /serveur en C++. Cependant je me demandais si il y avait en C++ un moyen de parser proprement les commandes que je réceptionne avec rcv() pour éviter de me retrouver avec des if() else() à rallonge.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void MyTCPclient::parseCommande(char * buffer) {
    	if (strcmp ("com1",buffer) != 0) {
    		// appel fonction MyTCPclient::com1
    	}
    	if (strcmp ("com2",buffer) != 0) {
    		// appel fonction MyTCPclient::com1
    	}
    	if (strcmp ("com3",buffer) != 0) {
    		// appel fonction MyTCPclient::com1
    	}
    ...
    }
    Pour avoir plutot un truc du genre (JAVA):

    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
     
    package test;
     
    import java.lang.reflect.Method;
     
    public class ClassMethodTest {
     
    	public static void main(String args[]) throws Exception {
     
    		Testing t = new Testing("val1", false);
    		Class tClass = t.getClass();
     
    		Method gs1Method = tClass.getMethod("getString1", new Class[] {});
    		String str1 = (String) gs1Method.invoke(t, new Object[] {});
    		System.out.println("getString1 returned: " + str1);
     
    		Method ss1Method = tClass.getMethod("setString1", new Class[] { String.class });
    		System.out.println("calling setString1 with 'val2'");
    		ss1Method.invoke(t, new Object[] { "val2" });
     
    		str1 = (String) gs1Method.invoke(t, new Object[] {});
    		System.out.println("getString1 returned: " + str1);
     
    	}
    }
    }
    En gros de pouvoir appeler toutes mes méthodes seulement en une condition. (je sais pas si c'est très clair ce que je raconte )

  2. #2
    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
    En C++/CLI, tu peux récupérer une méthode de classe par son nom, mais je ne le conseillerais pas de toute façon.
    Utilise un Dictionary<String^, Delegate^> à la place. Et utilise quelque chose de plus évolué que recv().

    ...Ou en C++11 natif, tu peux utiliser une std::map<std::string, std::function<(prototype commun à toutes tes fonctions de traitement)> >.
    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.

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    162
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 162
    Points : 62
    Points
    62
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    En C++/CLI, tu peux récupérer une méthode de classe par son nom, mais je ne le conseillerais pas de toute façon.
    Utilise un Dictionary<String^, Delegate^> à la place. Et utilise quelque chose de plus évolué que recv().

    ...Ou en C++11 natif, tu peux utiliser une std::map<std::string, std::function<(prototype commun à toutes tes fonctions de traitement)> >.
    Quelle serait une solution plus évolué que recv(), sachant que j'utilise du C++ natif ?

    Je vais testé la solution avec std::map, cependant je me demandais si mes fonctions ont chacune un type différents si cela fonctionnerait ?

  4. #4
    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
    Si tu programmes en C++ natif, pourquoi postes-tu dans la section consacrée au langage C++/CLI?

    je me demandais si mes fonctions ont chacune un type différents si cela fonctionnerait
    Hélas non. Le plus simple sera de faire, pour chaque fonction, une fonction qui récupère les différents arguments puis appelle l'original (dans le milieu des Appels de Procédure Distante, on appelle ça un "stub").
    Si tu programmes en C++11, tu devrais pouvoir faire ça assez facilement avec des fonctions lambda.
    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.

  5. #5
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 068
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 068
    Points : 12 111
    Points
    12 111
    Par défaut
    Regardez du coté du Design Pattern "Command".

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    162
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 162
    Points : 62
    Points
    62
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Si tu programmes en C++ natif, pourquoi postes-tu dans la section consacrée au langage C++/CLI?

    Hélas non. Le plus simple sera de faire, pour chaque fonction, une fonction qui récupère les différents arguments puis appelle l'original (dans le milieu des Appels de Procédure Distante, on appelle ça un "stub").
    Si tu programmes en C++11, tu devrais pouvoir faire ça assez facilement avec des fonctions lambda.
    Heu oui .. je viens de me rendre compte que je me suis trompé de section de forum... (boulet le type j'ai voulu allé trop vite )
    M'enfin les réponses attisent ma curiosité, je peux trouver de la doc sur le site à propos des "stubs" ?
    Si vous avez des liens utiles je suis preneurs.

  7. #7
    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
    En gros, le proxy et le stub sont deux objets qui servent d'intermédiaires, et donc le code est le plus souvent généré par des outils (je prends l'exemple de Java ici, qui marche ainsi pour son procédé de Remote Method Invocation (RMI)).

    Si je pars de cet exemple:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class Machin
    {
    public:
    	void Hello(void);
    	int FaireTruc(string const &chn, int a, int b);
    };

    Le proxy, c'est ce qu'il y a côté client, qui fera un truc de ce genre:
    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
    class MachinProxy
    {
    private:
    	Reseau& monReseau;
    	int monId;
    public:
    	MachinProxy(Reseau& reseau, int id) : monReseau(reseau), monId(id) { }
     
    	void Hello(void) {
    		Appel appel;
    		appel.SetThisId(monId);
    		appel.SetNomMethode("Hello");
    		monReseau.AppelDistant(appel);
    	}
    	int FaireTruc(string const &chn, int a, int b) {
    		Appel appel;
    		appel.SetThisId(monId);
    		appel.SetNomMethode("FaireTruc");
    		appel.SetString(0, chn);
    		appel.SetInt(1, a);
    		appel.SetInt(2, b);
    		monReseau.AppelDistant(appel);
    		return appel.GetInt(Appel::Retour);
    	}
    };

    Le stub, c'est ce qu'il y a côté client, qui fera un truc du genre:
    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
    class MachinStub : public StubBase //Doit forcément être le premier et non-virtuel
    {
    private:
    	Machin& leVraiMachin;
    public:
    	MachinStub(Machin& machin) : StubBase(), leVraiMachin(machin) { }
     
    	virtual map<string, PtrFonction> GetMap()
    	{
    		map<string, PtrFonction> ret;
    		ret["Hello"] = static_cast<PtrFonction>(&MachinStub::Hello); //Ça DOIT passer avec static_cast, sinon ça veut dire qu'on fait n'importe quoi.
    		ret["FaireTruc"] = static_cast<PtrFonction>(&MachinStub::FaireTruc);
    	}
     
    private:
     
    	void Hello(Appel &appel) {
    		(void)appel; //Hello est une fonction void(void), rien à traiter ici
    		leVraiMachin.Hello();
    	}
    	void FaireTruc(Appel &appel) {
    		int retour = leVraiMachin.FaireTruc(appel.GetString(0), appel.GetInt(1), appel.GetInt(2));
    		appel.SetInt(Appel::Retour, retour);
    	}
    };

    Attention par contre, c'est du code pré-C++11, on doit probablement pouvoir faire beaucoup plus propre de nos jours avec std::function<>, au niveau de remplissage de la map.

    Je joins le code complet que j'ai utilisé pour modéliser mon exemple. Il compile, mais il foire probablement à l'édition de liens, vu que rien n'est implémenté.
    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
    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
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    #include <string>
    #include <exception>
    #include <map>
    using namespace std;
     
    class Machin
    {
    public:
    	void Hello(void);
    	int FaireTruc(string const &chn, int a, int b);
    };
     
    class Appel
    {
    public:
    	static const int Retour = -1;
    	void SetNomMethode(string nom);
    	void SetThisId(int id);
    	void SetInt(int index, int valeur); 
    	void SetString(int index, string valeur);
     
    	string GetNomMethode() const;
    	int GetThisId() const;
    	int GetInt(int index) const;
    	string GetString(int index) const;
    private:
    	//Blabla implémentation
    };
     
    class Reseau
    {
    public:
    	void AppelDistant(Appel &);
    };
     
    class MachinProxy
    {
    private:
    	Reseau& monReseau;
    	int monId;
    public:
    	MachinProxy(Reseau& reseau, int id) : monReseau(reseau), monId(id) { }
     
    	void Hello(void) {
    		Appel appel;
    		appel.SetThisId(monId);
    		monReseau.AppelDistant(appel);
    	}
    	int FaireTruc(string const &chn, int a, int b) {
    		Appel appel;
    		appel.SetThisId(monId);
    		appel.SetString(0, chn);
    		appel.SetInt(1, a);
    		appel.SetInt(2, b);
    		monReseau.AppelDistant(appel);
    		return appel.GetInt(Appel::Retour);
    	}
    };
     
    class StubBase
    {
    protected:
    	typedef void(StubBase::*PtrFonction)(Appel &appel); //En C++11, on peut probablement utiliser std::function<void(Appel&)> à la place
     
    	virtual map<string, PtrFonction> GetMap() = 0;
    private:
    	map<string, PtrFonction> maMap;
    public:
    	void Initialiser() { //Doit être appelée APRÈS avoir construit l'objet complètement
    		maMap = GetMap();
    	}
     
    	void TraiterAppel(Appel& appel) {
    		PtrFonction ptr = maMap[appel.GetNomMethode()];
    		if(!ptr)
    			throw exception("Méthode inconnue");
     
    		(this->*ptr)(appel);
    	}
    };
     
    class MachinStub : public StubBase //Doit forcément être le premier et non-virtuel
    {
    private:
    	Machin& leVraiMachin;
    public:
    	MachinStub(Machin& machin) : StubBase(), leVraiMachin(machin) { }
     
    	virtual map<string, PtrFonction> GetMap()
    	{
    		map<string, PtrFonction> ret;
    		ret["Hello"] = static_cast<PtrFonction>(&MachinStub::Hello); //Ça DOIT passer avec static_cast, sinon ça veut dire qu'on fait n'importe quoi.
    		ret["FaireTruc"] = static_cast<PtrFonction>(&MachinStub::FaireTruc);
    	}
     
    private:
     
    	void Hello(Appel &appel) {
    		(void)appel; //Hello est une fonction void(void), rien à traiter ici
    		leVraiMachin.Hello();
    	}
    	void FaireTruc(Appel &appel) {
    		int retour = leVraiMachin.FaireTruc(appel.GetString(0), appel.GetInt(1), appel.GetInt(2));
    		appel.SetInt(Appel::Retour, retour);
    	}
    };

    Si ton but ultime est de re-créer une telle infrastructure, je rappelle qu'il conviendrait d'y inclure un utilitaire qui génère, à partir de la classe Machin, les fichiers MachinProxy.cpp et MachinStub.cpp.
    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.

Discussions similaires

  1. Transmettre des commandes à un process lancé par ksh
    Par jojolepabo dans le forum Linux
    Réponses: 3
    Dernier message: 19/10/2005, 16h05
  2. Réponses: 3
    Dernier message: 24/05/2004, 16h20
  3. parser des fichier .xml en perl
    Par djibril dans le forum Modules
    Réponses: 13
    Dernier message: 18/05/2004, 17h08
  4. Interception des commandes in et out
    Par KDD dans le forum x86 16-bits
    Réponses: 13
    Dernier message: 18/12/2002, 16h55
  5. Réponses: 3
    Dernier message: 02/09/2002, 18h49

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