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

Pointeur de caractère dans une DLL


Sujet :

Langage Delphi

  1. #1
    Membre éclairé
    Profil pro
    Développeur Java
    Inscrit en
    Mars 2004
    Messages
    624
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Mars 2004
    Messages : 624
    Points : 681
    Points
    681
    Par défaut Pointeur de caractère dans une DLL
    Bonjour,

    j'ai créé une dll qui retour un tableau de caractères.
    Le programme appelant appèle la fonction de la DLL.
    La DLL retourne la taille du résultat et stock le résultat dans une varaiable globale.
    Le programme appèle la DLL pour avoir le résultat de la DLL.
    Mais voilà, j'ai un gros souci.
    Voici le code du programme :
    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
     
    type
        TArrayOfChar = array of char ;
        PTArrayOfChar = ^TArrayOfChar ;
     
    begin
        { Prend le pointeur su la fonction GetResult }
        procresult := ExtensionGetResult[index] ;
     
        { Alloue la mémoire pour le résultat }
        SetLength(ResultatDll, Len) ;
     
        { Appel à GetResult }
        { procedure GetResult(PResult : PTArrayOfChar) ; stdcall; }
        procresult(@ResultatDll) ;
     
        { Copie le résultat dans une chaine }
        Result := '' ;
     
        for i := 0 to Len - 1 do
        begin
            Result := Result + ResultatDll[i] ;
        end ;
     
        { Libère l'espace alloué }
        SetLength(ResultatDll, 0) ;
    end;
    Et le code de la DLL :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    procedure GetResult(PResult : PTArrayOfChar) ; stdcall;
    var i : Integer ;
    begin
        for i := 0 to LenRF do
        begin
            PResult^[i] := ResultFunction[i] ;
        end ;
     
        FreeResult ;
    end ;
    Tout fonctionne mais lorsque sauf que lorsque le code du programme se termine j'ai ce message :

    Le projet SimpleWebScript.exe a provoqué une classe d'exception EInvalidPointer avec le message 'Opération de pointeur incorrecte'. Processus stoppé. Utilisez Pas-à-pas ou Exécuter pour continuer.
    Si dans la DLL j'enlève PResult^[i] := ResultFunction[i] ; ça fonctionne. J'en déduis donc que c'est ma gestion de pointer qui n'est pas bonne.

    J'ai donc lu plusieurs tutoriels sur la question (dont celui de developpez.com) et je ne comprend pas mon erreur.

  2. #2
    Rédacteur
    Avatar de Pedro
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    5 411
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 5 411
    Points : 8 078
    Points
    8 078
    Par défaut
    Salut
    Une erreur toute bête qui m'arrive régulièrement: tu n'aurais pas oublié stdcall quelque part? Par exemple, dans la déclaration de la structure de la méthode de la DLL dans l'éxecutable.

  3. #3
    Membre éclairé
    Profil pro
    Développeur Java
    Inscrit en
    Mars 2004
    Messages
    624
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Mars 2004
    Messages : 624
    Points : 681
    Points
    681
    Par défaut
    Je viens de vérifier malheureusement non.

    Et si j'essaye la procedure dans mon code ça fonctionne.

    Je viens de changer l'appel pour voir.
    En fait, on appel GetResult qui nous donne le pointer sur le résultat. Et une procedure FreeResult.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    {*******************************************************************************
     * Free memory of allocate to result
     ******************************************************************************}
    procedure FreeResult ; stdcall; export ;
    begin
        SetLength(ResultFunction, 0) ;
    end ;
     
    function GetResult : PTArrayOfChar ; stdcall; export ;
    begin
        Result := @ResultFunction ;
    end ;
    et dans mon programme principal :
    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
    var procresult : TProcResult ;
        procfree : TProcFree ;
        resultatDll : PTArrayOfChar ;
        i : Integer ;
    begin
        { Prend le pointeur su la fonction GetResult }
        procresult := ExtensionGetResult[index] ;
        procfree := ExtensionFreeResult[index] ;
     
        { Appel à GetResult }
        ResultatDLL := procresult ;
     
        { Copie le résultat dans une chaine }
        Result := '' ;
     
        for i := 0 to Len - 1 do
        begin
            Result := Result + ResultatDll^[i] ;
        end ;
     
        { Libère l'espace alloué }
        procfree ;
    end ;
    et là ça marche. Bizard

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 586
    Points : 25 262
    Points
    25 262
    Par défaut
    Au fait, pourquoi PTArrayOfChar au lieu d'un PChar ?

    car fait un échange de tableau dynamique entre DLL et Programme sans BordelMM.dll, c'est risqué !

    si c'est possible, l'utilisation du ShortString, simplifierait grandement la chose ... ou un PChar utilisé avec GetMem et FreeMem, comme en C, voir sinon, ces articles :

    http://delphi.developpez.com/faq/?pa...rstringdansdll

  5. #5
    Membre éclairé
    Profil pro
    Développeur Java
    Inscrit en
    Mars 2004
    Messages
    624
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Mars 2004
    Messages : 624
    Points : 681
    Points
    681
    Par défaut
    J'utilise un Array of char car les données peuvent être binaires. Je passe un pointer comme PChar. Je ne vois pas bien où est le problème ?

  6. #6
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 457
    Points
    28 457
    Par défaut
    l'erreur viens du "array of char"...cette déclaration correspond à un tableau DYNAMIQUE, et ça le fait vraiment pas sur une DLL

    si tu veux du binaire le mode classique est le suivant :

    côté DLL
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    function GetResult(pData:pointer; MaxSize:integer):integer; stdcall;
    begin
     Result:=DataSize;
     if (pData=nil)or(MaxSize=0) then exit; // on veux juste la taille
     if MaxSize>DataSize then MaxSize:=DataSize; // tronquer si nécessaire
     move(Data,pData^,MaxSize); // recopier les données
    end;
    côté EXE
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    var
     i:integer;
     s:string;
    begin
     i:=GetResult(nil,0); // obtient simplement la taille
     SetLength(s,i); // allocation mémoire
     GetResult(@s[1],i); // obtient maintenant les données
    end;

  7. #7
    Membre éclairé
    Profil pro
    Développeur Java
    Inscrit en
    Mars 2004
    Messages
    624
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Mars 2004
    Messages : 624
    Points : 681
    Points
    681
    Par défaut
    De quel typ doit être Data dans le move. Car si c'est une string ou array of char ça me retourne n'importe quoi.

    Par contre si data est une string et que j'utilise cette commande (sauf que ça me rajoute un #0 en final) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    StrPCopy(pData, Data) ;
    ça marche. Mais vu que je ne connaissais pas la commande move, je suppose que je l'utilise mal.

    Pour résoudre le problème voilà comment j'ai fait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
            for i := 0 to Result do
            begin
                PChar(pData)[i] := Data[i+1] ;
            end ;

Discussions similaires

  1. Réponses: 3
    Dernier message: 19/02/2007, 15h07
  2. [BP7] Problème chargement de ressource dans une DLL
    Par Alcatîz dans le forum Turbo Pascal
    Réponses: 11
    Dernier message: 26/07/2003, 21h36
  3. PB avec "self" dans une dll
    Par DiJiRiDouS dans le forum Langage
    Réponses: 2
    Dernier message: 21/02/2003, 09h32
  4. [VB6]Passage d'un tableau dans une DLL écrite en delphi
    Par flash dans le forum VB 6 et antérieur
    Réponses: 6
    Dernier message: 20/09/2002, 10h15
  5. Réponses: 3
    Dernier message: 09/05/2002, 01h39

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