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

Fonction dans une DLL agissant sur un TStringList


Sujet :

C++Builder

  1. #1
    Candidat au Club
    Inscrit en
    Octobre 2009
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Octobre 2009
    Messages : 6
    Points : 4
    Points
    4
    Par défaut Fonction dans une DLL agissant sur un TStringList
    Salut,

    Un peu de contexte d'abord :
    J'ai écrit un programme à but scientifique qui (entre autres choses) traite des données pouvant se présenter dans des formats différents selon leur origine. Mon programme gère pour l'instant 2 formats très courants mais évidemment tous les formats ne sont pas gérés. Pour ces formats non gérés, je voulais donner la possibilité à leurs utilisateurs d'écrire une DLL à partir d'un template que je fournis. Cette DLL s'interfacerait avec le programme principal pour remplir les conteneurs de données.

    Mon implémentation :
    A ce stade encore expérimental, la DLL se contente de recevoir un TStringList du programme principal pour le remplir avec des lignes (peu importe les valeurs pour le moment) contenant les données sous forme "double x ; double y", les données sur 2 colonnes séparées par un point-virgule quoi. Le code donne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    extern "C" __declspec(dllexport) bool __stdcall AddData(TStringList &zob)
    {
    zob.Clear();
    for (int i = 1 ; i < 101 ; i++)
            {
            double gn = (i - 1) * 10.0;
            double gnn = 100.0 * exp(-gn);
            zob.Add(FloatToStr(gn) + ";" + FloatToStr(gnn));
            }
    return 1;
    }
    Au niveau du programme principal, la DLL est bien chargée, la fonction est trouvée et est appelée comme suit :

    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
     
    AnsiString DLLpath;
    DLLpath = "Project1.dll";
    MainFm->HandleDLL = LoadLibrary(DLLpath.c_str());
    if (MainFm->HandleDLL)
    {
    MainFm->AddDataOnly = (MYDLLFUNCB)(GetProcAddress(MainFm->HandleDLL , "AddData"));
    if (MainFm->AddDataOnly)
    {
    MainFm->AddDataOnly(*DVHToAdd->ProcessedData);
    }
    else ShowMessage("Function not found");
    FreeLibrary(MainFm->HandleDLL);
    }
    //At this point, ProcessedData should hold the parsed DVH data in the "dose|volume" format
    int IterLim = DVHToAdd->ProcessedData->Count;
    for (int k = 0 ; k != IterLim ; k++)
    {
    AnsiString TempStr = DVHToAdd->ProcessedData->Strings[k];
    char *TempChar = strtok(TempStr.c_str(),",/|;");
    DVHToAdd->SeriesDer->AddX(StrToFloat(TempChar));
    TempChar = strtok(NULL,",/|;");
    DVHToAdd->SeriesDer->YValue[k] = StrToFloat(TempChar);
    }
    Le typedef sur la fonction importée est défini par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    typedef bool (__stdcall *MYDLLFUNCB)(TStringList &zob);
    Le problème :
    Quand j'exécute pas-à-pas, je vois que la DLL est chargée, la fonction trouvée et que le TStringList revient de l'appel de fonction avec un count à 100 laissant penser que des éléments ont bien été ajoutés sauf qu'aux lignes suivantes, où le programme boucle sur les lignes du TStringList, j'ai une erreur d'accès mémoire. Ca ressemble à une situation où les emplacements mémoire qui contiennent effectivement les lignes rajoutées sont perdus ou ne collent plus au retour de la DLL.
    Notez que j'ai essayé avec et sans le rajout aux projets de la librairie Borland pour gestion de mémoire etc. J'ai aussi essayé avec un prototype de fonction où je passe le pointeur vers le TStringList mais les symptômes sont exactement les mêmes.
    Ca ne me parait pas particulièrement exotique de faire remplir une liste de chaines par une DLL donc c'est forcément moi qui fait une connerie, laquelle ?

    Merci !

  2. #2
    Candidat au Club
    Inscrit en
    Octobre 2009
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Octobre 2009
    Messages : 6
    Points : 4
    Points
    4
    Par défaut
    Dites voir, ce serait pas parce que je libère la DLL avant d'utiliser le contenu du TStringList ?
    Je viens de faire l'essai en remplissant un vecteur de AnsiString et si je libère la librairie avant d'utiliser le contenu du vecteur, le contenu est perdu (et inversement je peux l'utiliser tant que la DLL n'est pas libérée) mais c'est pas justement le principe de passer un pointeur en paramètre de la fonction ? Si on passe le pointeur, c'est la variable pointée qui est affectée par la fonction et pas une variable temporaire du même type dans le scope de la fonction non ?

    Comment faut-il que je définisse la fonction dans la DLL pour qu'elle modifie la variable qui lui est passée en argument alors ?

  3. #3
    Membre chevronné
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Responsable de compte
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Points : 2 187
    Points
    2 187
    Billets dans le blog
    1
    Par défaut
    Salut
    ton code me semble correct
    mais n'a tu pas oublier de créer une instance de ta StringList
    cordialement

  4. #4
    Candidat au Club
    Inscrit en
    Octobre 2009
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Octobre 2009
    Messages : 6
    Points : 4
    Points
    4
    Par défaut
    Salut,

    Oui, la TStringList est créee un peu plus haut dans le code, j'ai pas collé cette partie parce qu'il faut bien s'arrêter quelquepart

    Comme je disais dans mon second post, le code fonctionne si je ne détruis pas le Handle avant de me servir des données dans la TStringList. Et là, je comprends pas, si je passe le pointeur vers l'objet en paramètre, ça devrait remplir l'objet lui-même, pas une copie temporaire dans le scope de la fonction de la DLL nan ?
    Pour que les données récupérées dans la DLL persistent, je suis obligé d'envoyer un pointeur vers un vector<string> puis de copier le contenu du vector vers mon TStringList du programme principal.

    Je peux aussi reformuler mon interrogation dans un cadre plus simple :

    Imaginons que j'ai un tableau de pointeur vers des entiers, je passe un pointeur vers ce tableau en paramètre d'une fonction qui crée dans son scope 2 variables entières et les stocke dans le tableau. Quand je reviens au programme principal, les 2 valeurs auront-elles disparues de mon tableau ?

    ++

  5. #5
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 390
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 390
    Points : 1 777
    Points
    1 777
    Par défaut
    Salut !

    Le mieux serait que la dll crée sa propre StringList.
    Donc la fonction exportée se limiterait à retourner l'adresse de cette Stringlist une fois remplie.
    Il suffit alors de remplir une deuxième Stringlist (avec le contenu de celle de la dll) juste avant de libérer la dll qui libérera sa propre mémoire.

    A plus !

  6. #6
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Avec Delphi, il faut utiliser l'unité "ShareMem" pour utiliser des String depuis une DLL sans vautrer la mémoire.

    Vérifie que ce n'est pas AUSSI le cas avec BCB, on ne sait jamais.

Discussions similaires

  1. [ARM] Appel d'une fonction dans une dll
    Par mosfet dans le forum Autres architectures
    Réponses: 3
    Dernier message: 28/03/2007, 08h15
  2. ordinal d'une fonction dans une dll
    Par peijnoob dans le forum Windows
    Réponses: 20
    Dernier message: 10/11/2006, 10h32
  3. [VB]exporter fonction dans une DLL
    Par SubZero2 dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 05/04/2006, 15h59
  4. Point d'entrée d'une fonction dans une DLL
    Par Muetdhiver dans le forum MFC
    Réponses: 5
    Dernier message: 15/02/2006, 23h49
  5. [VStudio 6] pb avec fonctions dans une DLL
    Par MogDeChNord dans le forum MFC
    Réponses: 8
    Dernier message: 08/01/2004, 08h57

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