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 :

Comment utiliser une variable globale de dll ?


Sujet :

Langage Delphi

  1. #1
    Candidat au Club
    Inscrit en
    Février 2007
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 10
    Points : 3
    Points
    3
    Par défaut Comment utiliser une variable globale de dll ?
    J'ai une dll qui contient une variable exportée que je dois initialiser.
    Quelqu'un sait-il comment faire ?
    Merci

  2. #2
    Membre éprouvé
    Avatar de CapJack
    Homme Profil pro
    Prof, développeur amateur vaguement éclairé...
    Inscrit en
    Mars 2004
    Messages
    624
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Prof, développeur amateur vaguement éclairé...
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2004
    Messages : 624
    Points : 988
    Points
    988
    Par défaut
    Il y a plusieurs démarches.

    Si la variable n'a à être initialisée qu'au démarrage, il suffit d'utiliser une syntaxe du type :

    Il est ausi possible d'effectuer des initialisations entre le "begin" et le "end." de la dll.

    Sinon, et sans que ce soit exclusif, il faut définir une fonction d'affectation.

    Voilà un code de test pour la dll :

    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
    library DllExportVariable;
     
     
    uses
      SysUtils,
      Classes;
     
    {$R *.res}
     
    var I : Integer;
     
    function GetValue : Integer;stdcall;
     begin
      Result := I;
     end;
     
    procedure SetValue(AValue : Integer);stdcall;
     begin
      I := AValue;
     end;
     
    exports GetValue,SetValue;
     
    begin
     I := 324;
    end.
    Et un exemple de code à insérer dans l'unité de la fiche, pour l'utilisation (fiche avec un bouton Button1).

    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
    implementation
     
    {$R *.dfm}
     
    function  GetValue : Integer; stdcall; external 'DllExportVariable.dll' name 'GetValue';
    procedure SetValue(AValue : Integer); stdcall; external 'DllExportVariable.dll' name 'SetValue';
     
    procedure TForm1.Button1Click(Sender: TObject);
    begin
     ShowMessage(IntToStr(GetValue));
     SetValue(-3251);
     ShowMessage(IntToStr(GetValue));
    end;
     
    end.

  3. #3
    Candidat au Club
    Inscrit en
    Février 2007
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 10
    Points : 3
    Points
    3
    Par défaut
    Je ne peux pas toucher à la dll car elle est fournie avec un matériel.
    Je sais juste qu'elle contient une variable de type booléen que je dois absolument mettre à true (elle est à false par défaut) pour utiliser certaines fonctionnalités de mon matériel.
    Donc une autre idée ?

  4. #4
    Membre éprouvé
    Avatar de CapJack
    Homme Profil pro
    Prof, développeur amateur vaguement éclairé...
    Inscrit en
    Mars 2004
    Messages
    624
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Prof, développeur amateur vaguement éclairé...
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2004
    Messages : 624
    Points : 988
    Points
    988
    Par défaut
    Citation Envoyé par Chamatho Voir le message
    Je ne peux pas toucher à la dll car elle est fournie avec un matériel.
    Tu aurais pu le dire tout de suite, ça m'aurait évité de perdre mon temps...

    Non, pas d'idée. A part peut-être consulter la documentation dudit matériel ?

  5. #5
    Membre chevronné

    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2002
    Messages
    1 288
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2002
    Messages : 1 288
    Points : 1 936
    Points
    1 936
    Par défaut
    Et dans la doc de la dll, il n'y a rien qui explique l'état de cette variable?
    Delphi 7/XE2/XE3
    C#
    Oracle 9i à 12c
    SQL Server 2008 à 2014

  6. #6
    Candidat au Club
    Inscrit en
    Février 2007
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 10
    Points : 3
    Points
    3
    Par défaut
    Citation Envoyé par Linkin Voir le message
    Et dans la doc de la dll, il n'y a rien qui explique l'état de cette variable?
    C'est une variable de type booléen. Suivant sa valeur les fonctions de la dll travaillent différemment. Rien à dire de plus.

    Delphi ne serait-il pas capable de mettre à jour des variables de dll ?

  7. #7
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 696
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 696
    Points : 13 135
    Points
    13 135
    Par défaut
    Citation Envoyé par Chamatho Voir le message
    Delphi ne serait-il pas capable de mettre à jour des variables de dll ?
    S'il n'y a pas de procédure exportée pour initialiser ces variables, aucune chance. Delphi ou tout autres systèmes de développement.

    Récupérer la liste des procédures et fonctions n'est pas compliqué avec Delphi, il suffit de charger la DLL avec LoadLibrary et d'afficher les modules chargés pour avoir une liste exhaustives des fonctions exportées. Mais les paramètres à passer seront toujours manquants.

    Comme l'a dit CapJack, seule la doc peut t'aider.

  8. #8
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 858
    Points : 11 300
    Points
    11 300
    Billets dans le blog
    6
    Par défaut
    Je ne peux pas toucher à la dll car elle est fournie avec un matériel.
    je dois absolument mettre à true (elle est à false par défaut) pour utiliser certaines fonctionnalités de mon matériel.
    si cette variable n'a pas de setter, c'est pê parce que la valeur de ce booléen est déterminée en fonction du matériel relié, ou par le type de licence d'exploitation ?
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  9. #9
    Candidat au Club
    Inscrit en
    Février 2007
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 10
    Points : 3
    Points
    3
    Par défaut
    Citation Envoyé par tourlourou Voir le message
    si cette variable n'a pas de setter, c'est pê parce que la valeur de ce booléen est déterminée en fonction du matériel relié, ou par le type de licence d'exploitation ?
    Non, non : la doc me dit bien qu'il faut que j'initialise cette variable ...

    "setter" c'est quoi ?


    Citation Envoyé par Andnotor Voir le message
    S'il n'y a pas de procédure exportée pour initialiser ces variables, aucune chance. Delphi ou tout autres systèmes de développement.
    Ben si justement en C++ c'est possible d'utiliser une variable déclarée en global dans une dll.

    Car voici la suite de mes investigations mais toujours sans solution pour Delphi :

    en C++ (que je ne maitrise pas : je me suis fait aider) et pour ceux qui connaissent (ils pourront peut être faire le parallèle) il faut mettre la ligne suivante dans le fichier .h :
    extern "C" __declspec(dllimport) BOOL LeNomVariable

    et dans le programme il suffit de mettre
    LeNomVariable = 1
    pour que cela fonctionne

    C'est donc bien une variable.

    Avec tdump.exe de delphi quand on regarde la dll, on trouve dans la section exports la ligne
    LeNomVariable avec des adresses devant (ce qui ne m'avance pas ..)
    Par contre pour les fonctions ou procédures, leur nom est précédé de _ et suivi de @ et un nombre.
    La déclaration est donc légèrement différente, peut-être qu'il y a une raison ?

    Malgré tout cela je suis toujours coincé ...

  10. #10
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    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 459
    Points : 24 873
    Points
    24 873
    Par défaut
    _LeNomVariable@4, normalement le chiffre après l'@ en export C (Name-decoration convention) c'est la taille des paramètres ... 4 indiquerait un BOOL ou un Pointeur ...

    Il faut que tu contactes le frabricant pour lui demander comme est géré l'export de variable en C++, je ne suis pas convaincu que ce soit un standard géré par VB ou Delphi ... sinon il y aurait en standard un GetPtrAdress comme GetProcAddress mais pour des zones de mémoires partagées ...


    sinon Totalement au hazard, faut bien essayé des truc (essaye '_LeNomVariable' ou 'LeNomVariable')

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    procedure LeNomVariable(AValue : BOOL); stdcall; external 'DllExportVariable.dll' name '_LeNomVariable';
    ou

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    function LeNomVariable(AValue : BOOL): BOOL; stdcall; external 'DllExportVariable.dll' name '_LeNomVariable';
    Dans ce cas, il n'y aurait qu'un Setter (accesseur en écriture), après tout il n'est peut-être pas utile de la consulter puisque c'est un flag d'utilisation, ...

    enfin une autre idée farfelue

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    function LeNomVariable: ^BOOL; stdcall; external 'DllExportVariable.dll' name '_LeNomVariable';
    en fait, on peut imaginer que la fonction renvoie un pointeur sur la variable (on peut exporter des classes donc ...), et que la mémoire a été mise en Read\Write ...
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  11. #11
    Membre confirmé
    Avatar de gb_68
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2006
    Messages
    232
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 232
    Points : 546
    Points
    546
    Par défaut
    Bonjour,
    tu peux en effet récupérer dynamiquement la variable par GetProcAddr() à condition de savoir son nom exact .
    Un utilitaire comme Dependency Walker pourra t'aider.
    J'ai testé en VC++/Delphi :
    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #ifdef DLLEXPORTINT_EXPORTS
    #define DLLEXPORTINT_API __declspec(dllexport)
    #else
    #define DLLEXPORTINT_API __declspec(dllimport)
    #endif
    extern DLLEXPORTINT_API int IntCpp;
    extern "C" DLLEXPORTINT_API int IntC; // ne sera donc pas "décoré"
    //...
    DLLEXPORTINT_API int IntCpp=1;
    DLLEXPORTINT_API int IntC=2;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    var
      FLib : HMODULE;
      PIntC,PIntCpp : PInteger;
    begin
      FLib := LoadLibrary('DllExportInt.dll');
      PIntCpp  := PInteger(GetProcAddress(FLib,'?IntCpp@@3HA' ));
      PIntC    := PInteger(GetProcAddress(FLib,'IntC' ));
    Et ça fonctionne

  12. #12
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    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 459
    Points : 24 873
    Points
    24 873
    Par défaut
    MERCI gb_68 !
    C'est très interessant !

    Connais-tu aussi la solution pour exporter en Delphi, une telle variable ?
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  13. #13
    Membre confirmé
    Avatar de gb_68
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2006
    Messages
    232
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 232
    Points : 546
    Points
    546
    Par défaut
    En Delphi 2006 (Turbo)
    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
    library TestDllVar;
     
    uses
      SysUtils, Classes;
    {$R *.res}
     
    const ConstInt : Integer = 10;
    var IntInit : Integer = 20;
     
    var Int: Integer;
    exports Int;
     
    begin
      Int := 30;
    end.
    Seul 'Int' peut être exporté pour que cela compile (mais pas avec IntInit ). Le symbole est bien exporté selon Dependency Walker. Sauf que le compilateur supprime le Int := 30; car selon lui
    [Pascal Conseil] TestDllVar.dpr(31): H2077 La valeur affectée à 'Int' n'est jamais utilisée
    et j'obtiens 0 en VC++. Mais en rusant un peu
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var Int: Integer;
    exports Int;
     
    procedure Init;
    begin
      Int := 30;
    end;
     
    begin
      Init;
    end.
    la on retrouve bien la valeur 30 en C++ .
    A noter que l'aide n'indique rien sur une quelconque possibilité d'utiliser exports avec autre chose que des fonctions/procédures.

    Sinon l'aide précise que
    Le langage Delphi ne gère pas l'importation de variables depuis les DLL ou les assemblages.
    Alors pour réaliser l'import statique d'une variable, il faut un peu bricoler
    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
    type
      PThunkCode = ^TThunkCode;
     
      TThunkCode = packed record
      strict private
        Jump : array[0..1] of Byte;
      public
        Addr : PPointer;    
      end;
     
      TIntegerImport = record
      strict private
        FPInt : PInteger;
        function GetValue : Integer; inline;
        procedure SetValue( AValue : Integer ); inline;
      public
        procedure FromFakeFucntion( proc : TProcedure ); inline;
        property Value : Integer read GetValue write SetValue;
      end;
     
    { TIntegerImport }
    procedure TIntegerImport.FromFakeFucntion(proc: TProcedure);
    begin
       FPInt := PThunkCode(@proc).Addr^;
    end;
     
    function TIntegerImport.GetValue: Integer;
    begin
      Result := FPInt^;
    end;
     
    procedure TIntegerImport.SetValue(AValue: Integer);
    begin
      FPInt^ := AValue;
    end;
     
    procedure ___IntC; external 'DllExportInt.dll' name 'IntC';
     
    procedure TForm1.Button3Click(Sender: TObject);
    var IntC : TIntegerImport;
    begin
      IntC.FromFakeFucntion(___IntC);
      IntC.Value := 100;
    end;
    ou on peut aussi se contenter de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    procedure ___IntC; external 'DllExportInt.dll' name 'IntC'; // force le chargement statique de la Dll
     
    procedure TForm1.Button4Click(Sender: TObject);
    begin
      FLib := GetModuleHandle('DllExportInt.dll'); // la bibliothèque est déjà chargée
      // un GetModuleHandle suffit (à la place de LoadLibrary/FreeLibrary)
      PIntCpp  := PInteger(GetProcAddress(FLib,'?IntCpp@@3HA' ));
      PIntC    := PInteger(GetProcAddress(FLib,'IntC' ));
    end;

  14. #14
    Candidat au Club
    Inscrit en
    Février 2007
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 10
    Points : 3
    Points
    3
    Par défaut
    Merci de vos idées.

    Dès que je peux, j'essaye et je vous tiens au courant !

  15. #15
    Membre éprouvé
    Avatar de CapJack
    Homme Profil pro
    Prof, développeur amateur vaguement éclairé...
    Inscrit en
    Mars 2004
    Messages
    624
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Prof, développeur amateur vaguement éclairé...
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2004
    Messages : 624
    Points : 988
    Points
    988
    Par défaut
    Ooooh, bien vu, gb_68 ! J'avais moi-même essayé de trouver une telle méthode, mais je me suis arrêté quand le compilateur m'a envoyé promener sur l'export d'une variable initialisée, ce qui fait que je n'ai même pas pensé à exporter une variable non initialisée, et je n'ai pas cherché plus loin faute de temps.

    Je stocke un raccourci vers ce fil, ça ouvre des perspectives intéressantes.

Discussions similaires

  1. Réponses: 1
    Dernier message: 26/02/2009, 07h11
  2. Réponses: 5
    Dernier message: 04/05/2006, 21h02
  3. [sql] comment utiliser une variable global
    Par imedg dans le forum Oracle
    Réponses: 21
    Dernier message: 02/05/2006, 15h21
  4. Comment déclarer une variable globale
    Par davkick dans le forum C
    Réponses: 13
    Dernier message: 20/05/2005, 18h50

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