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++ Discussion :

Tout fonctionne, j'aimerais savoir pourquoi (DLL + Prog orientée objet)


Sujet :

C++

  1. #1
    Membre habitué Avatar de Nightmare Theater
    Homme Profil pro
    Ingénieur après-vente
    Inscrit en
    Juin 2007
    Messages
    127
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Ingénieur après-vente
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 127
    Points : 174
    Points
    174
    Par défaut Tout fonctionne, j'aimerais savoir pourquoi (DLL + Prog orientée objet)
    Bonjour à tous,

    Dans le cadre d'un projet de stage je dois programmer un wrapper pour LabVIEW. Avant de m'attaquer au gros du projet, j'ai voulu faire des tests concernant la création de DLLs, et plus précisément de DLLs utilisant des objets. Je ne suis pas informaticien, n'étudie pas l'informatique et n'ai jamais programmé un projet en C++. En tâtonnant je suis arrivé à faire fonctionner mon programme comme je le souhaite, donc de ce point de vue, pas de solution miracle à donner.

    Cependant, ce fut du tâtonnement et certaines choses fonctionnent sans que je comprennent pourquoi. Il serait fort aimable si quelqu'un pouvait m'expliquer pourquoi.

    Mon Projet inclut les fichiers suivants:
    * stdafx.h (header contenant tous mes includes)
    * targetver.h (crèè automatiquement, je ne l'ai pas touché)
    * Object dummi.h (définition de mon objet)
    * dllmain.cpp (le main de la dll. J'y ai juste ajouté la déclaration de mes fonctions)
    * stdafx.cpp (encore une fois, un fichier vide contenant tous mes includes)
    * ObjDef.def (un .def avec la liste des fonctions accessibles en appelant la DLL)
    * Projet DLL C++.cpp (mon fichier principal avec mes fonctions. Je vais essayer de limiter mes questions à ce fichier).

    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
    // Projet DLL C++.cpp : Defines the exported functions for the DLL application.
    //
     
    #include "stdafx.h"
     
     
    extern "C" Dummi * __stdcall CreateObject(void)
    {
    	Dummi dum;
    	dum.Init(); // Initialisation des variables private de mon objet au cas où les fonctions read seraient lues avant d'être écrites
    	return &dum;
    }
     
    extern "C" float __stdcall Addition(Dummi * d1, float a, float b)
    {
    	return d1->Addieren(a, b);
    }
     
    extern "C" void __stdcall GiveName(Dummi * d1) // fonction pour tenter d'écrire dans le private de mon objet
    {
    	d1->Setname("myobject");
    }
     
    extern "C" char * __stdcall GetName(Dummi * d1) // fonction pour lire dans le private de mon objet
    {
    	return d1->Getname();
    }
     
    extern "C" void __stdcall GiveVal(Dummi * d1, float a) // fonction pour tenter d'écrire dans le private de mon objet
    {
    	d1->Setvalue(a);
    }
     
    extern "C" float __stdcall GetVal(Dummi * d1) )// fonction pour lire dans le private de mon objet
    {
    	return d1->Getvalue();
    }
    Question 1: J'ai cru comprendre que extern "C" et __stdcall sont obligatoires. Que font ils et qu'apportent-ils à la fonction? Extern "C" restreint l'utilisation de certaines fonctions propres au C++ (les string par exemple, qui doivent être remplacés par des char*, sous peine de se prendre un warning et que les fonctions les utilisant ne fonctionnent pas une fois appelés depuis la DLL). Y-a-t-il une alternative?

    Question 2: Ligne 16, 21, 26, 31 et 36. Quand je fais référence à mon objet dans mes fonctions, je dois utiliser -> (par exemple d1->Getvalue();). d1.Getvalue(); et d1::Getvalue(); ne fonctionnent pas. Pourquoi et où se situe la différence entre -> . et ::

    Question 3: Si l'interret de grouper ses includes dans un seul (stdafx.h) me parait logique, je ne vois pas l'intérêt de répéter l'opération dans stdafx.cpp . En quoi est-il conseillé de le faire.

    J'utilise Vusual Studio 2010.

    Merci d'avance

  2. #2
    screetch
    Invité(e)
    Par défaut
    c'est globalement très bizarre que ca marche.
    Commencons par les questions que tu poses:

    1) extern "C" indique un linkage "C" au lieu de C++, ce qui veut dire que la foncion est exportée par son nom. Si tu effectues un linkage C++ la fonction est exportée via sa signature, qui contient le nom plus des tonnes de caractères bizarroides, et il n'est pas possible de connaitre son nom d'export donc l'import est difficile.
    On peut passer des objets via un linkage C, mais il n'y aura pas de vérification du type; c'est plus dangereux.

    2) on utilise monObjet.membre(), ou bien monPointeurSurObjet->membre, ou bien classe::membre, dans des situations distinctes.
    Ici tu as un pointeur sur un objet, la seule facon d'btenir le membre c'est d'utiliser -> qui est l'opérateur de résolution de membre pour un pointeur.
    . est l'opérateur de résolution de membre pour un objet, pas un pointeur sur un objet.
    enfin, :: est l'opérateur de résolution de nom, il permet d'obtenir un membre d'une classe, pas un membre d'un objet. Il est assez peu utilisé (sauf pour les namespace)

    3) stdafx est l'unité de précompilation. Si tu groupes tous les include dans stdafx.h, tous les fichiers qui l'utilisent, au lieu d'inclure les fichiers "a la main", vont utiliser le fichier précompilé, ce qui va beaucoup plus vite.
    Ce fichier précompilé est généré en compilant stdafx.cpp qui est un fichier special. stdafx.cpp devrait uniquement unclire stdafx.h. Le compilateur ne compile pas stdafx.cpp comme un fichier normal, il génère le fichier de précompilation.


    et pour info:
    4) ton code contient une grosse faute. dans
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    extern "C" Dummi * __stdcall CreateObject(void)
    {
    	Dummi dum;
    	dum.Init(); // Initialisation des variables private de mon objet au cas où les fonctions read seraient lues avant d'être écrites
    	return &dum;
    }
    tu crées une variable locale, retourne une adresse dessus. Ta variable etant locale, elle cesse d'exister dés la fin de la méthode et elle est detruite, mais le pointeur que tu retournes continue d'exister. Tu renvoies donc un pointeur sur quelque chose qui a été detruit, ce qui peut marcher dans de très rares cas mais risque surtout de planter l'application dés que tu voudras faire queque chose d'utile.
    pour que l'objet continue a vivre il doit être alloué sur le tas avec l'opérateur new, et libéré plus tard avec l'opérateur delete:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    extern "C" Dummi * __stdcall CreateObject(void)
    {
    	Dummi* dum = new Dummi;
    	dum->Init(); // Initialisation des variables private de mon objet au cas où les fonctions read seraient lues avant d'être écrites
    	return dum;
    }
    extern "C" void __stdcall DestroyObject(Dummi* dummy)
    {
            delete dummi;
    }
    5) ton code utilise des termes en allemand et des termes en anglais. Dummy a un y a la fin

    6) Enfin il y a une autre manière de faire, bien plus pratique:
    tu ne gardes que les CreateDummi et DestroyDummi
    dans ton projet principal, tu as:
    idummi.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class IDummi
    {
    protected:
      IDummi() { }
      ~IDummi() { }
    public:
      virtual Addieren(float a, float b) = 0;
      virtual void Givename(const std::string& name) = 0;
      virtual const std::string& Getname() = 0;
      virtual void Givevalue(float v) = 0;
      virtual float Getvalue() = 0;
    };
    dans ta dll, tu as dummi.h qui contient la classe dummi qui implemente ces fonctions

    CreateObject et DestroyObject retournent un pointeur sur un IDummy, et le programme principal peut appeler des méthodes sur le IDummy. Leur implémentation est uniquement dans la DLL cependant.

  3. #3
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Bonjour,

    Citation Envoyé par Nightmare Theater Voir le message
    En tâtonnant je suis arrivé à faire fonctionner mon programme comme je le souhaite, donc de ce point de vue, pas de solution miracle à donner.
    A la lecture du code que tu proposes, tu as juste de la chance.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    extern "C" Dummi * __stdcall CreateObject(void)
    {
    	Dummi dum;
    	dum.Init(); // Initialisation des variables private de mon objet au cas où les fonctions read seraient lues avant d'être écrites
    	return &dum;
    }
    Cette fonction est erronée. L'objet retourné est détruit dès que l'exécution quitte la fonction.
    Toute utilisation ultérieure du pointeur est juste un comportement indéfini. Ou dit autrement, cela peut marcher, planter ou faire le café.

    Citation Envoyé par Nightmare Theater Voir le message
    Cependant, ce fut du tâtonnement et certaines choses fonctionnent sans que je comprennent pourquoi. Il serait fort aimable si quelqu'un pouvait m'expliquer pourquoi.
    Je suis toujours épaté par cette démarche de faire du logiciel sans considérer que cela nécessite un enseignement/une formation dédiée (osons : que c'est un métier à part entière). Puis-je devenir thermicien par tâtonnement ? Pourra-t-on m'expliquer sans autre forme pourquoi le chaud ça brûle et le froid ça refroidi ?

    Citation Envoyé par Nightmare Theater Voir le message
    Question 1: J'ai cru comprendre que extern "C" et __stdcall sont obligatoires. Que font ils et qu'apportent-ils à la fonction? Extern "C" restreint l'utilisation de certaines fonctions propres au C++ (les string par exemple, qui doivent être remplacés par des char*, sous peine de se prendre un warning et que les fonctions les utilisant ne fonctionnent pas une fois appelés depuis la DLL). Y-a-t-il une alternative?
    extern "C" et __stdcall ne sont nullement obligatoire. Il existe d'autres façons d'exporter des objets et des fonctions. Les DLL et les fonctions exportées/importées sont pas tant liées aux C++ qu'à l'OS et aux compilateurs.
    extern "C" indique au compilateur que la fonction est définie ailleurs et doit être considérée comme une fonction C (cela a des impacts sur la façon dont le nom 'binaire' de la fonction est construit entre autres).

    __stdcall n'est pas C++ standard mais spécifique à visual C++ pour indiquer une façon de passer les paramètres, de nettoyer la pile, de décorer les noms. Bref, de la cuisine interne de compilateur.

    __declspec( dllexport ) (ou __declspec( dllimport )) peuvent être utilisés avec Visual C++ pour des DLLs Visual C++


    Citation Envoyé par Nightmare Theater Voir le message
    Question 2: Ligne 16, 21, 26, 31 et 36. Quand je fais référence à mon objet dans mes fonctions, je dois utiliser -> (par exemple d1->Getvalue();). d1.Getvalue(); et d1::Getvalue(); ne fonctionnent pas. Pourquoi et où se situe la différence entre -> . et ::
    La meilleure réponse serait probablement de renvoyer à un cours de C++. Mais puisqu'on peut programmer sans apprendre :

    :: est l'opérateur de portée. On y trouve à gauche un nom identifiant un élément de portée : espace de nom ou classe. Il sert à préciser où une identifiant doit être cherché si la portée implicite ne suffit pas (conflit d'espace de nom, fonction de classe, fonction masquée, etc.).

    . est utilisé lorsque l'expression à gauche dénote un objet.

    -> est utilisé lorsque l'expression à gauche dénote un pointeur sur un objet.


    Citation Envoyé par Nightmare Theater Voir le message
    Question 3: Si l'interret de grouper ses includes dans un seul (stdafx.h) me parait logique, je ne vois pas l'intérêt de répéter l'opération dans stdafx.cpp . En quoi est-il conseillé de le faire.
    stdafx.h n'est pas fait pour contenir tous les includes d'un projet. Il est, dans un environnement Visual C++, là pour contenir les en-têtes précompilés. Ces en-têtes précompilés sont destinés à être compilés une fois par la compilation de stdafx.cpp. Ensuite, lorsque d'autres fichiers sources incluent stdafx.h, Visual C++ va chercher la version précompilée pour ne pas avoir à les recompiler lors du traitement de ces fichiers.
    Cela est essentiellement lié à la façon dont les fichiers sources (unités de traduction) sont gérées en C++. Les en-têtes précompilés (stdafx.h/stdafx.cpp étant leur mise en oeuvre classique par Visual C++) sont une façon d'optimiser les temps de compilation.
    F.A.Q : Organisation du code source.

  4. #4
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par screetch Voir le message
    Il est assez peu utilisé (sauf pour les namespace)
    et pour les fonctions de classes (statiques) et lorsqu'on appelle une fonction d'une classe de base et lorsqu'il y a un conflit (multi héritage par expl) et ...

  5. #5
    screetch
    Invité(e)
    Par défaut
    tu dis ca parce que t'es jaloux que je t'aie grillé de 8 minutes

  6. #6
    Membre habitué Avatar de Nightmare Theater
    Homme Profil pro
    Ingénieur après-vente
    Inscrit en
    Juin 2007
    Messages
    127
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Ingénieur après-vente
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 127
    Points : 174
    Points
    174
    Par défaut
    Merci pour vos réponses.

    Je vais commencer par
    Citation Envoyé par 3DArchi Voir le message
    Je suis toujours épaté par cette démarche de faire du logiciel sans considérer que cela nécessite un enseignement/une formation dédiée (osons : que c'est un métier à part entière). Puis-je devenir thermicien par tâtonnement ? Pourra-t-on m'expliquer sans autre forme pourquoi le chaud ça brûle et le froid ça refroidi ?
    Disons que ce n'est pas par choix. A la définition du sujet de stage, on pensait que je n'aurais pas à mettre les mains dans le cambouis et utiliser des DLL déjà existantes pour me concentrer sur la partie qui m’intéresse vraiment : acquisition de données, traitement et réutilisation pour commander des moteurs. Il se trouve qu'on s'est foutu le doigt dans l'oeil jusqu'au coude, que j'ai pas de DLL exploitable et que donc je dois jouer du Visual Studio pour avoir des données exploitables sous LabVIEW. Si je pouvais laisser ça à un informaticien, je le ferais volontiers car ce n'est pour moi qu'une sorte de trou noir où mon temps et mon énergie disparaissent.

    Citation Envoyé par screetch
    1) extern "C" indique un linkage "C" au lieu de C++, ce qui veut dire que la foncion est exportée par son nom. Si tu effectues un linkage C++ la fonction est exportée via sa signature, qui contient le nom plus des tonnes de caractères bizarroides, et il n'est pas possible de connaitre son nom d'export donc l'import est difficile.
    On peut passer des objets via un linkage C, mais il n'y aura pas de vérification du type; c'est plus dangereux.
    Merci, j'ai compris. Du coup je suis obligé d'utiliser un Linkage C et c'est aussi pour ça que j'ai à rentrer tous les types des arguments à la main. Je vous dit grand merci .

    Idem pour 2) et 3), me voilà tout éclairé (tant et si bien que j'en deviendrais presque phosphorescent).

    Citation Envoyé par 3DArchi
    Cette fonction est erronée. L'objet retourné est détruit dès que l'exécution quitte la fonction.
    Toute utilisation ultérieure du pointeur est juste un comportement indéfini. Ou dit autrement, cela peut marcher, planter ou faire le café.
    Merci de la précision. Malheureusement ça ne fait pas le café, mais merci pour l'idée. J'en parlerais à mon maître de stage. Il me semble que ça marche car, lors de l'import d'une fonction d'un DLL sous LabVIEW, je peux demander à ce que les variables soient stockées en mémoire jusqu'à la fermeture de l'application. Je ne savais pas qu'on pouvait faire autrement, je vais tester ça demain. Merci du conseil

    Citation Envoyé par screetch
    5) ton code utilise des termes en allemand et des termes en anglais. Dummy a un y a la fin
    Je navigue en permanence entre l'anglais, l'allemand et le français (entre le personnel, les clients francophones, les anglophones et les germanophones). Je me mélange les pinceaux souvent entre les langues et je ne m'en suis pas rendu compte. Je corrigerais ça pour que ce soit un peu plus cohérent. Quand au Dummy... Je méritearais presque le titre.

    Citation Envoyé par 3DArchi
    La meilleure réponse serait probablement de renvoyer à un cours de C++. Mais puisqu'on peut programmer sans apprendre
    Comme dit précédemment, ce n'est pas la partie de mon projet sur laquelle je serais notée et je n'ai pas spécialement envie de devenir programmeur (comme tu le dis, c'est un métier, et autant laisser faire les professionnels). Je n'ai pas la prétention d'affirmer connaître le C++ en autodidacte. Mais de la même manière, si un relais de l'armoire électrique qui alimente ton PC crame, que tu dois finir un projet et que tu n'a aucun électricien pour le changer. Je suppose que tu te renseignerais sur comment ça marche et lequel acheter, puis tu le commandera et changera le relais défectueux. Tu pourrais très bien apprendre tout sur le design d'armoires électriques, mais admettons que tu n'a pas de vocation à devenir électricien, je suppose que tu te borneras à ce qui te sera utile

    Citation Envoyé par 3DArchi
    F.A.Q : Organisation du code source.
    Grand Merci

  7. #7
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut
    Citation Envoyé par Nightmare Theater Voir le message
    Merci de la précision. Malheureusement ça ne fait pas le café, mais merci pour l'idée. J'en parlerais à mon maître de stage. Il me semble que ça marche car, lors de l'import d'une fonction d'un DLL sous LabVIEW, je peux demander à ce que les variables soient stockées en mémoire jusqu'à la fermeture de l'application. Je ne savais pas qu'on pouvait faire autrement, je vais tester ça demain. Merci du conseil
    Attention, ce que j'ai voulu dire par indéterminé et qu'il peut faire le café, c'est que le code tel que tu nous l'a présenté risque de planter à n'importe quel moment du fait qu'il utilise un comportement indéterminé. Pour l'instant, ça a l'air de marcher mais c'est juste de la chance. Je suis près à parier que dès que tu enchaîneras plus de fonctions complexes, le code partira dans les choux (et probablement à un endroit qui n'aura rien à voir). Screetch propose une solution par gestion dynamique de l'espace mémoire. C'est une solution. En tout cas, tu ne peux utiliser une référence/pointeur sur un objet après qu'il soit détruit.

    Citation Envoyé par Nightmare Theater Voir le message
    Mais de la même manière, si un relais de l'armoire électrique qui alimente ton PC crame, que tu dois finir un projet et que tu n'a aucun électricien pour le changer. Je suppose que tu te renseignerais sur comment ça marche et lequel acheter, puis tu le commandera et changera le relais défectueux. Tu pourrais très bien apprendre tout sur le design d'armoires électriques, mais admettons que tu n'a pas de vocation à devenir électricien, je suppose que tu te borneras à ce qui te sera utile
    C'est une petite polémique HS mais je pourrais renchérir qu'en faisant de la sorte je peux au mieux griller mon PC/installation éléctrique ou pire rester coller, les deux doigts sur le relais

  8. #8
    Membre habitué Avatar de Nightmare Theater
    Homme Profil pro
    Ingénieur après-vente
    Inscrit en
    Juin 2007
    Messages
    127
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Ingénieur après-vente
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 127
    Points : 174
    Points
    174
    Par défaut
    Merci pour les précisions. J'avais bien compris pour le café et l'allocation mémoire. Simplement je n'avais jamais entendu l'expression et elle m'a faite rire. Cet exemple était surtout pour voir comment intégrer une DLL avec un objet dans LabVIEW. J'ai regardé, l'objet avec lequel je devrais travailler à bien été programmé par des Informaticiens (des vrais ) et semble correspondre à tes remarques et à celles de screetch. Ce fut en tout cas très instructif


    Quand à la "polémique", je vois très bien ce que tu veux dire, j'ai grillé une alim il y a peu en voulant faire mon Mc Gyver et en prenant une standard 400W sans fusible. Elle a pris feu 4h après le lancement du PC. Je m'égare...
    Le problème je pense est toujours le même, en particulier concernant les stagiaires. Vous devez en voir passer des dizaines par jour sur le forum. Souvent, en Genie Meca, Electronique, Physique ou autre domaine technique, on se retrouve avec de la prog et on est pas préparés (les cours de C++ que j'avais suivi en IUT étaient une vaste supercherie vu qu'ils ont "omis" l'orientation objet et qu'on s'est contenté de programmé du C avec comme seule différence iostream et string. Du coup on se retrouve lâchés à devoir pondre du code sans aucune idée concernant les règles élémentaires de syntaxe et de développement de projet. Pour peu qu'il n'y ai pas d'informaticiens dans la boite, on se retrouve à polluer les forums de questions stupides. Durant mon précédent stage, j'avais Netah25 en maitre de stage qui me filait des coups de main. Là y'a personne. D'où le pourquoi du comment

  9. #9
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    no problemo. Les forum sont bien là pour ça (pallier à la misère de la recherche, entre autre ). Mais de temps en temps, ça fait du bien à son égo de rappeler que comprendre une syntaxe est à la portée de tous, faire un programme demande du métier. (sinon ça ressemble au plâtre que je peux faire sur mes murs )

  10. #10
    Membre habitué Avatar de Nightmare Theater
    Homme Profil pro
    Ingénieur après-vente
    Inscrit en
    Juin 2007
    Messages
    127
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Ingénieur après-vente
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 127
    Points : 174
    Points
    174
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    no problemo. Les forum sont bien là pour ça (pallier à la misère de la recherche, entre autre ). Mais de temps en temps, ça fait du bien à son égo de rappeler que comprendre une syntaxe est à la portée de tous, faire un programme demande du métier. (sinon ça ressemble au plâtre que je peux faire sur mes murs )


    En tout cas merci pour les précisions.

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

Discussions similaires

  1. Je viens de m'inscrire sur ce forum j'aimerais savoir comment ça fonctionne
    Par cherubin999 dans le forum Mode d'emploi & aide aux nouveaux
    Réponses: 2
    Dernier message: 14/05/2014, 17h07
  2. J'aimerais comprendre pourquoi ça ne fonctionne pas
    Par JamesBond002 dans le forum Débuter avec Java
    Réponses: 13
    Dernier message: 28/05/2013, 15h49
  3. Réponses: 4
    Dernier message: 30/08/2006, 17h52
  4. pourquoi ce prog plante ?
    Par stokastik dans le forum C
    Réponses: 10
    Dernier message: 22/08/2006, 12h07
  5. Réponses: 8
    Dernier message: 17/10/2002, 12h52

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