J'ai une dll qui contient une variable exportée que je dois initialiser.
Quelqu'un sait-il comment faire ?
Merci
J'ai une dll qui contient une variable exportée que je dois initialiser.
Quelqu'un sait-il comment faire ?
Merci
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.
Code : Sélectionner tout - Visualiser dans une fenêtre à part var I : Integer = 324;
Sinon, et sans que ce soit exclusif, il faut définir une fonction d'affectation.
Voilà un code de test pour la dll :
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
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.
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.
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 ?
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
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.
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 ?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.
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 !
Non, non : la doc me dit bien qu'il faut que j'initialise cette variable ...
"setter" c'est quoi ?
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é ...
_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')
ou
Code : Sélectionner tout - Visualiser dans une fenêtre à part procedure LeNomVariable(AValue : 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, ...
Code : Sélectionner tout - Visualiser dans une fenêtre à part function LeNomVariable(AValue : BOOL): BOOL; stdcall; external 'DllExportVariable.dll' name '_LeNomVariable';
enfin une autre idée farfelue
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 ...
Code : Sélectionner tout - Visualiser dans une fenêtre à part function LeNomVariable: ^BOOL; stdcall; external 'DllExportVariable.dll' name '_LeNomVariable';
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
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;Et ça fonctionne
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' ));
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
En Delphi 2006 (Turbo)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
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.et j'obtiens 0 en VC++. Mais en rusant un peu[Pascal Conseil] TestDllVar.dpr(31): H2077 La valeur affectée à 'Int' n'est jamais utiliséela on retrouve bien la valeur 30 en C++ .
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.
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 queAlors pour réaliser l'import statique d'une variable, il faut un peu bricolerLe langage Delphi ne gère pas l'importation de variables depuis les DLL ou les assemblages.
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
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;
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;
Merci de vos idées.
Dès que je peux, j'essaye et je vous tiens au courant !
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.
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager