silverman
Nombre de messages : 970 Age : 52 Localisation : Picardie Date d'inscription : 18/03/2015
| Sujet: ADR_STRING(V) Ven 9 Fév 2018 - 18:08 | |
| Il n'existe pas de moyen pour transmettre/recevoir une chaine de caractère à/d' une dll, puisque l'adresse d'une chaine transmise par la fonction ADR n'est pas la bonne. Il ne sera pas possible de créer une FNC pour remédier à cela à cause de l'allocation dynamique de la mémoire. Cette fonction permettrait de résoudre ce pb. | |
|
Jack Admin
Nombre de messages : 2394 Date d'inscription : 28/05/2007
| Sujet: Re: ADR_STRING(V) Ven 9 Fév 2018 - 18:26 | |
| - silverman a écrit:
- l'adresse d'une chaine transmise par la fonction ADR n'est pas la bonne.
Que veux-tu dire par là ? Le sujet des adresses de chaînes de caractères est vaste. Il y a des chaines de caractères terminées par la valeur 0, et d'autres pas. _________________ username : panoramic@jack-panoramic password : panoramic123 | |
|
Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: ADR_STRING(V) Ven 9 Fév 2018 - 18:39 | |
| Si, on peut faire ça. Pour KGF.dll, je le fais tout le temps. Dans une DLL, on peut lire une chaîne Panoramic passée en paramètre, et on peut également remplacer son contenu par d'autres caractères. La seule chose impossible, c'est de changer sa longueur et d'en créer une nouvelle, à partir de la DLL. KGF.dll est écrit en Delphi V6 Personal Eidition. Voici comment on fait, dans cette configuration (à adapter éventuellement d'autres langues): Panoramic: - Code:
-
dim a$ a$ = "Ceci est ma chaîne de caractères" res% = dll_call1("Test",adr(a$)) Lire cette chaîne dans la fonction Test de la DLL en Delphi - Code:
-
function Test(chaine: pstring):integer; stdcall; export; var s: string; begin s := chaîne^; showmessage('La chaîne contient: '+s); ... result := Length(s); end; En fait, l'expression Panoramic adr(a$) fournit l'adresse d'un pointeur vers la chaîne. C'est exactement ce que représente un pstring en Delphi. Là où pstring n'est pas défini, il suffit de le déclarer comme ceci: - Code:
-
type pstring = ^string; end; Maintenant, pour changer les caractères du string passé en paramètre, je passe par une boucle utilisant des pointeurs de type pbyte (là encore: pbyte = ^byte;). Comme ceci, en remplaçant le texte de l'exemple ci-dessus par des "x" (ou n'importe quoi d'autre): - Code:
-
procedure CopyStringToPanoramic(sInput: string; aOutput: pstring); var pi, po: pbyte; begin pi := pbyte(@sinput[1]); po := pbyte(pinteger(aOutput)^); // ici, on prend la valeur passée par Panoramic: adr(a$) // on la considère comme un pointeur vers un entier (justement, vers la vraie adresse du string) // on déréférence ce pointeur ce qui fournit la vraie adresse du string // et pour finir, on considère cette adresse comme une adresse d'un octet (pbyte) // maintenant, on boucle jusqu'à ce qu'on bute contre la fin de la chaîne en sortie (a$). // Cette fain est toujours déterminée par un octet de valeur 0 repeat if pi^<>0 then begin // la chaîne en entrée n'est pas terminée ? po^ := pi^; // copier un octet inc(pi); // passer au prochain caractère en entrée end else begin // la chaîne en entrée est terminée po^ := 32; // alors remplir par des espaces end; inc(po); // passer au prochain caractère en sortie until pi^=0; // et arrêter si la sortie est complète end;
function Test(chaine: pstring):integer; stdcall; export; var s, snew: string; begin s := chaîne^; showmessage('La chaîne contient: '+s); ... sNew := 'xxxxxxxxxxx'; CopyStringToPanoramic(snew,chaine); result := Length(s); end; Bon courage ! EDITMais attention à ce qut tu fais avec une chaîne de caractères reçue de Panoramic ! Tu auras par exemple des problèmes si tu veux la mettre dans une TStringList, par exemple. Ceci tient à une optimisation interne de Delphi. Tant que tu ne fais que "copier" une chaîne, en réalité, tu ne déplaces qu'un pointeur vers la chaîne, en incrémentant son compteur de référence. Lorsque le programme s'arrête, la chaîne de caractères Panoramic d'origine est supprimée. Et lorsque Delphi veut supprimer la TSTringList, par exemple, le pointeur vers la chaîne indique un endroit dans la mémoire qui a déjà été libéré. Et donc, BOUM ! Violation de mémoire. Les manières d'éviter cela: 1. au lieu de faire - Code:
-
MaStringList.Add(chaîne^); ou - Code:
-
var s: string; begin s := chaine^; MaStringList.Add(s); il faut utiliser un système de copie similaire à celui décrit ci-dessus pour copier la chaîne Panoramic dans une variable Delphi intermédiaire, puis affecter cette variable. 2. on affecte une chaîne modifiée pour "tromper" le compilateur de Delphi: - Code:
-
MaStringList.Add(Trim(chaîne^)+' '); Simple, non ? | |
|
silverman
Nombre de messages : 970 Age : 52 Localisation : Picardie Date d'inscription : 18/03/2015
| Sujet: Re: ADR_STRING(V) Sam 10 Fév 2018 - 11:31 | |
| @jack en fait c'est pour pouvoir envoyer le bon pointeur(descripteur ?) de chaine à une dll windows. Dans cet extrait de code: - Code:
-
Path$=dir_current$ lpszLongPath%=ADR(Path$) dword% = DLL_CALL3("GetShortPathNameA", lpszLongPath%, lpszShortPath%, cchBuffer%) 'lpszLongPath%' n'est pas bon. La bonne valeur serait lpszLongPath%=peek(ADR(Path$)) mais peek ne fonctionne que sur un octet. @klaus c'est valable pour une dll que l'on aura codé, mais pas pour une dll windows. | |
|
Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: ADR_STRING(V) Sam 10 Fév 2018 - 12:26 | |
| - Citation :
- c'est valable pour une dll que l'on aura codé, mais pas pour une dll windows.
Pas tout à fait. Une DLL Windows s'attend à trouver un PCHAR, par un PSTRING. Or, adr(s$) fournit l'adresse d'un string, et non un pointeur sur les caractères. C'est peut-être un problème de terminologie, mais en Delphi, c'est très clair: l'adresse d'un string n'est pas la même chose qu'un PCHAR. Il se trouve que depuis le début, l'interface DLL de Panoramic fonctionne comme ça, avec la fonction adr() donnant l'adresse du string. Changer cela signifie imposer littéralement des dizaines de milliers de modifications à faire dans les codes de tous ceux qui codent des DLLs en Delphi pour Panoramic. Je parle bien sûr de KGF.dll, mais ne suis certainement pas le seul. Si Jack y voit un intérêt, il pourrait ajouter une fonction du type ADR_PCHAR(s$)pour aller dans ton sens. Mais pour ma part, je suis fermement opposé au changement de fonctionnement de la fonction ADR(). | |
|
silverman
Nombre de messages : 970 Age : 52 Localisation : Picardie Date d'inscription : 18/03/2015
| Sujet: Re: ADR_STRING(V) Sam 10 Fév 2018 - 12:52 | |
| - klaus a écrit:
- Mais pour ma part, je suis fermement opposé au changement de fonctionnement de la fonction ADR().
Ce n'est pas ce que j'ai suggéré. Il n'est pas question de modifier la fonction ADR. Ce que je souhaite, c'est une nouvelle fonction qui s'appelerait ADR_STRING(S$)(ou ADR_PCHAR(S$) si tu préfères) et qui retournerait comme valeur : peek(ADR(S$)). Cela permettrais de pouvoir utiliser les fonctions des dll windows qui nécessite un pointeur de chaine comme celle-ci par exemple. Indirectement, cela rejoint ta demande d'extension de la fonction PEEK. A la limite, si PEEK32 est créé, cette demande deviendrait superflu. | |
|
Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: ADR_STRING(V) Sam 10 Fév 2018 - 12:59 | |
| Là, on se rejoint tout à fait, Silverman. C'était justement une de mes motivations pour proposer l'extension de PEEK et POKE. | |
|