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 :

dll, chaine, pointeurs [Débutant(e)]


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Janvier 2010
    Messages
    58
    Détails du profil
    Informations forums :
    Inscription : Janvier 2010
    Messages : 58
    Par défaut dll, chaine, pointeurs
    Hello,

    J'ai une dll à réaliser. Avec quelques tuto et VC++, j'ai réussi à faire une dll qui me retourne un entier, aucun problème, tout va bien.

    Or, j'ai voulu la modifier pour qu'elle me retourne une chaine, mais je ne m'en sors vraiment pas. Je merdoye dans les pointeurs à coup sûr. Pourriez-vous m'aiguiller svp ?

    Le code qui suit est le seul qui me retourne quelquechose sans planter. Évidemment, ce qui est retourné n'est pas de la forme souhaitée.

    Je suis sensée me retrouver avec un date formatée AAAAMMJJHHSSMM, mais je me retrouve avec une suite de nombre incohérents, que j'ai interprété comme étant une @ mémoire. (quoi que j'en doute car ce cnombre est toujours identique)

    Alors comment my' prendre ? transtyper ma chaine en entier ? Trouver une soluce pour passer mon char en paramètre ?

    Je suis sûr que mon erreur est toute bête ...

    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
    // dllmain.cpp : Définit le point d'entrée pour l'application DLL.
    #include "stdafx.h"
    #include "time.h"
    #include <iostream>
     
     
    extern "C" __declspec(dllexport)void retourne_ts(int parametre, char TimestampARecuperer);
     
     
    BOOL APIENTRY DllMain( HMODULE hModule,
                           DWORD  ul_reason_for_call,
                           LPVOID lpReserved
    					 )
    {
    	switch (ul_reason_for_call)
    	{
    	case DLL_PROCESS_ATTACH:
    	case DLL_THREAD_ATTACH:
    	case DLL_THREAD_DETACH:
    	case DLL_PROCESS_DETACH:
    		break;
    	}
    	return TRUE;
    }
     
     
    void retourne_ts(int parametre, char TimestampARecuperer)
    {
    	time_t timestamp;
        struct tm * t;
     
        timestamp = parametre;
        t = localtime(&timestamp);
     
    	int jour[2] = {t->tm_mday};
    	int mois[2] = {1+t->tm_mon};
    	int annee[4] = {1900+t->tm_year};
    	int heure[2] = {t->tm_hour};
    	int minutes[2] = {t->tm_min};
    	int secondes [2] = {t->tm_sec};
    	char separateur [] = "/";
    	char Timestampconcatene[15]; 
    	sprintf(Timestampconcatene, "%02u%02u%02u%02u%02u%02u",*annee, *mois, *jour , *heure, *minutes, *secondes);
    	TimestampARecuperer = *Timestampconcatene;
    }
    Et voici le code dont je me suis inspiré (vous noterez l'utilisation de '&' dans les paramètres int des fonctions. Chose que je n'arrive pas à réutiliser avec les char

    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
    // dllmain.cpp : Définit le point d'entrée pour l'application DLL.
    #include "stdafx.h"
     
    // This function is used to calculate the total area of a parallelepiped rectangle
    int BoxArea(int L, int H, int W);
    // This function is used to calculate the volume of a parallelepiped rectangle
    int BoxVolume(int L, int H, int W);
    // This function is used to get the dimensions of a rectangular parallelepiped
    // calculate the area and volume, then pass the calculated values to the
    // function that called it.
    extern "C" __declspec(dllexport)void BoxProperties(int Length, int Height,
                                        int Width, int& Area);
     
     
    BOOL APIENTRY DllMain( HMODULE hModule,
                           DWORD  ul_reason_for_call,
                           LPVOID lpReserved
    					 )
    {
    	switch (ul_reason_for_call)
    	{
    	case DLL_PROCESS_ATTACH:
    	case DLL_THREAD_ATTACH:
    	case DLL_THREAD_DETACH:
    	case DLL_PROCESS_DETACH:
    		break;
    	}
    	return TRUE;
    }
    int BoxArea(int L, int H, int W)
    {
        return 2 * ((L*H) + (L*W) + (H*W));
    }
     
    int BoxVolume(int L, int H, int W)
    {
        return L * H * W;
    }
     
    void BoxProperties(int L, int H, int W, int& A)
    {
        A = 666;
        //V = BoxVolume(L, H, W);
    }
    Merci d'avance.

  2. #2
    Membre confirmé
    Inscrit en
    Janvier 2010
    Messages
    58
    Détails du profil
    Informations forums :
    Inscription : Janvier 2010
    Messages : 58
    Par défaut
    petite avancée, si je fais



    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
     
     
    // dllmain.cpp : Définit le point d'entrée pour l'application DLL.
    #include "stdafx.h"
    #include "time.h"
     
    extern "C" __declspec(dllexport)void retourne_ts(int parametre, char& TimestampARecuperer);
     
     
    BOOL APIENTRY DllMain( HMODULE hModule,
                           DWORD  ul_reason_for_call,
                           LPVOID lpReserved
    					 )
    {
    	switch (ul_reason_for_call)
    	{
    	case DLL_PROCESS_ATTACH:
    	case DLL_THREAD_ATTACH:
    	case DLL_THREAD_DETACH:
    	case DLL_PROCESS_DETACH:
    		break;
    	}
    	return TRUE;
    }
     
     
    void retourne_ts(int parametre, char& TimestampARecuperer)
    {
    	char test[256] = "testchaine";
    	TimestampARecuperer = *test;
    }
    Ma chaine passe bien, mais je ne récupère que le premier caractère de ma chaine

    Y'a pas moyen de déclarer des String() comme en java ou quelque chose dans le genre ?

  3. #3
    Membre Expert
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Par défaut
    euh .... std::string ...

  4. #4
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par Joel F Voir le message
    euh .... std::string ...
    Non pas, non pas !

    Le fait que le standard C++ ne définit pas d'ABI fait que les templates ne peuvent pas faire partie d'une interface de DLL. Les risques sont importants que cette DLL soit utilisée par un programme n'utilisant pas la même version de la librairie standard, ou (encore plus agaçant) par les même options de compilation. Et on obtiendra quelque chose qui plante, qui plante, qui plante.

    Il est recommandé d'utiliser des pointeurs char* au niveau des interfaces, et (pour éviter les buffers overflow) un contrôle de la taille de ces pointeurs.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    void get_times_stamp(char* out, std::size_t outsize)
    {
      char b[] = "timestamp";
      std::size_t = std::min(sizeof(b), outsize);
      std::copy(b, b+outsize, out);
    }
    Quand à la raison de ton erreur htrouve, tu passe en paramètre 1 caractère en référence. Tu n'obtiendra donc qu'un caractère en sortie de ta fonction.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  5. #5
    Membre Expert
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    Le fait que le standard C++ ne définit pas d'ABI fait que les templates ne peuvent pas faire partie d'une interface de DLL. Les risques sont importants que cette DLL soit utilisée par un programme n'utilisant pas la même version de la librairie standard, ou (encore plus agaçant) par les même options de compilation. Et on obtiendra quelque chose qui plante, qui plante, qui plante.

    certes, le coup des options de compilations, c'est purement MSVC ? Ou a t on le meme probleme avec des .so ou leur fonctionnement est-il tout a fait différent ?

  6. #6
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par Joel F Voir le message

    certes, le coup des options de compilations, c'est purement MSVC ? Ou a t on le meme probleme avec des .so ou leur fonctionnement est-il tout a fait différent ?
    Tous les compilateurs sont impactés - il ne s'agit pas nécessairement de MSVC. Bien sûr, ça dépends fortement de l'implémentation de la librairie standard, et de la façon dont le compilateur fonctionne. Sans ABI (abstract binary interface) standardisée, on ne peut pas prédire ce qui peut se passer. Les .so peuvent être impactés de la même manière - mais il me semble que la librairie standard de g++ est beaucoup plus solide que celle de MS vis à vis de ce point. Mais ça ne veut pas dire que les opérateurs globaux ::new() et ::delete() auront la même définition dans les deux modules.

    Supposons que ça soit le cas, et que mon module ajoute un élément à un vecteur créé par l'application. Cet ajout va peut être nécessiter un resize() du vecteur, et donc une nouvelle allocation, copie et désallocation du bloc précédent. Au moment de la desallocation, quel delete est utilisé ? Le surchargé ? le non surchargé ? Que se passe-t-il si le ::delete() du module tente d'utiliser des informations de debug qui n'existe pas ? Comment le détecte-t-il ? etc.

    Pas d'ABI, redéfinition de comportements, etc: le C++, c'est quand même dangereux à utiliser au niveau des interfaces Et je ne parle même pas des templates, dont la génération peut changer en fonction des options de compilation

    Citation Envoyé par JolyLoic
    Je mitigerais légèrement cet avis. En général, on fait des DLL pour l'une des trois raisons suivantes :

    - Pour de la modularité, y compris avec des partenaires externes, ou avec d'autres langages de programmation. Dans ce cas, en effet, éviter des DLL avec du C++ dans l'interface, à plus forte raison un template.
    Le C++ est a éviter, encore que le problème se situe en fait bien souvent sur sur le runtime utilisé par l'un et l'autre des modules, ainsi que sur les options de compilation qui peuvent avoir un impact sur le code des classes utilisées dans l'interface. Je m'explique : supposons que la classe X soit ainsi faite:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    class X
    {
    private:
    #if DEBUG
      int instance_count;
    #endif
      ...
    };
    Dès lors que je vais compiler un module en debug, ma classe n'aura plus la même définition que celle, compilée en release, utilisée par l'application qui instancie mon module. Son comportement en sera donc modifié.

    Mais en faisant très attention (et notamment en ne faisant pas ce que ke présente ci-dessus), on peut limiter le problème. Il y a quelques règles à respecter :

    1) en paramètre à une fonction, on ne passe que des pointeurs ou des références.
    2) le module qui instancie une classe la détruit (par exemple, au cas où new/delete auraient été surchargés dans le module qui utilise l'instance).

    Citation Envoyé par JolyLoic
    - Pour de la modularité dans une application que l'on contrôle de bout en bout: Pouvoir réaliser des livraisons partielles, faire des montées de version sans arrêter le produit... Dans ce cas, et à condition bien entendu d'utiliser partout les mêmes options de compilation, le gain apporté par l'utilisation de vrais types (avec du RAII) dans les interfaces me semble supérieur au coût
    Voui, ça marche. En fait, c'est même l'un des rares cas où ça marche. Mais lorsque le projet est composé de plusieurs dizaines de DLL générées par toute une équipe (ça existe), c'est quelque fois difficile d'accorder les options de compilation sur tous les projets (et généralement, c'est le client qui s'en apperçoit, hein ?)

    Citation Envoyé par JolyLoic
    - Parce qu'on n'a pas compris qu'une bibliothèque statique était plus adaptée.
    +1 Et personnellement, je commence à avoir une impression de "j'aime pas" lorsque je vois des DLL dans un projet. Et je suis incapable de savoir d'où provient cette impression.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  7. #7
    Membre confirmé
    Inscrit en
    Janvier 2010
    Messages
    58
    Détails du profil
    Informations forums :
    Inscription : Janvier 2010
    Messages : 58
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    Quand à la raison de ton erreur htrouve, tu passe en paramètre 1 caractère en référence. Tu n'obtiendra donc qu'un caractère en sortie de ta fonction.


    Bonjour et merci pour vos éléments de réponses. Cependant, je ne comprends pas pourquoi je ne passe qu'un seul paramètres alors que mon char peut en contenir 256 dans mon code.

    Et quelle est la différence, dans le prototype de la fonction entre passer
    char* mavariable et char& mavariable ?

  8. #8
    Membre confirmé
    Inscrit en
    Janvier 2010
    Messages
    58
    Détails du profil
    Informations forums :
    Inscription : Janvier 2010
    Messages : 58
    Par défaut
    Bon, j'ai réussi à faire quelque chose qui 'fonctionne', ma chaine retournée est entière cette fois !

    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
    // dllmain.cpp : Définit le point d'entrée pour l'application DLL.
    #include "stdafx.h"
    #include "time.h"
    #include <iostream>
    #include <sstream>
     
     
    extern "C" __declspec(dllexport)void retourne_ts(int parametre, char& TimestampARecuperer);
     
     
    BOOL APIENTRY DllMain( HMODULE hModule,
                           DWORD  ul_reason_for_call,
                           LPVOID lpReserved
    					 )
    {
    	switch (ul_reason_for_call)
    	{
    	case DLL_PROCESS_ATTACH:
    	case DLL_THREAD_ATTACH:
    	case DLL_THREAD_DETACH:
    	case DLL_PROCESS_DETACH:
    		break;
    	}
    	return TRUE;
    }
     
     
    void retourne_ts(int parametre, char& TimestampARecuperer)
    {
    	char test[256] = "timestamp";
    	TimestampARecuperer =  *test;
    	strcpy(&TimestampARecuperer,test);
    }
    Si vous avez mieux, je ne demande qu'à comprendre et apprendre !

    Encore merci.

  9. #9
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    Non pas, non pas !
    Je mitigerais légèrement cet avis. En général, on fait des DLL pour l'une des trois raisons suivantes :

    - Pour de la modularité, y compris avec des partenaires externes, ou avec d'autres langages de programmation. Dans ce cas, en effet, éviter des DLL avec du C++ dans l'interface, à plus forte raison un template.
    - Pour de la modularité dans une application que l'on contrôle de bout en bout: Pouvoir réaliser des livraisons partielles, faire des montées de version sans arrêter le produit... Dans ce cas, et à condition bien entendu d'utiliser partout les mêmes options de compilation, le gain apporté par l'utilisation de vrais types (avec du RAII) dans les interfaces me semble supérieur au coût
    - Parce qu'on n'a pas compris qu'une bibliothèque statique était plus adaptée.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  10. #10
    Membre confirmé
    Inscrit en
    Janvier 2010
    Messages
    58
    Détails du profil
    Informations forums :
    Inscription : Janvier 2010
    Messages : 58
    Par défaut
    Euh franchement j'en sais rien, j'imagine que ca te retourne 01/01/1970

    J'ai pas trop compris le commentaire d'Emmanuel sur 'passe en paramètre 1 caractère en référence'.

    Moi, tel que je le vois, je passe en paramètre un entier, et ca renvoit une chaine. Mais je ne comprends pas pourquoi avec mon premier code, ca ne me retournait que la 1e lettre de ma chaine.

    Alors que quand je testais en printf, j'avais bien toute ma chaine formatée de retournée.

    J'ai réussi à m'en sortir avec strcopy, mais j'aimerais bien comprendre le pourquoi du comment de mes erreurs en fait.

Discussions similaires

  1. Réponses: 5
    Dernier message: 22/04/2013, 11h06
  2. Chargement explicte DLL et pointeur de fonction
    Par Bundy*Al dans le forum Débuter
    Réponses: 2
    Dernier message: 17/04/2013, 11h04
  3. Cours liste chainée (pointeur)
    Par neufrdb dans le forum Débuter avec Java
    Réponses: 14
    Dernier message: 27/05/2011, 16h07
  4. Apeller fonction DLL avec pointeurs en Delphi
    Par dacid dans le forum Delphi
    Réponses: 2
    Dernier message: 11/08/2006, 12h11
  5. Chaines et pointeurs mais pas "const"
    Par hpfx dans le forum C
    Réponses: 9
    Dernier message: 05/10/2003, 20h23

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