Novembre 2024 | Lun | Mar | Mer | Jeu | Ven | Sam | Dim |
---|
| | | | 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 | | Calendrier |
|
|
| Astuce : créer mémoire tampon(très utile pour CALL_DLLx()) | |
| | Auteur | Message |
---|
silverman
Nombre de messages : 970 Age : 52 Localisation : Picardie Date d'inscription : 18/03/2015
| Sujet: Astuce : créer mémoire tampon(très utile pour CALL_DLLx()) Sam 25 Avr 2015 - 18:39 | |
| EDIT2: qq changement dant le source pour être compatible avec la bibliothèque ici : créer memoire tampon, applicationEDIT1: qq correction de phrase dans le post et le source pour améliorer la compréhension. Bonjour à tous, Lorsque l'on utilise une dll, on a parfois besoin de lui passer un pointeur qui pointe vers une mémoire tampon, pour récupérer des données par exemple. Je n'ai pas trouvé de code sur le forum pour faire ça(j'ai peut être mal charché aussi ), alors voici mon astuce en Panoramic pur, sans DLL. Le principe est simple: - fabriquer une chaine de caractère de longueur voulu, avec le caractère null(chr$(0)).(Ca donne des octets null) - récupérer avec ADR() le pointeur de cette chaine, pointeur qui est l'adresse ou sont stocké les octets null ---> cette adresse permet de lire/modifier ces octets, opération effectué à l'aide d'une sub() C'est de l'écriture direct dans l'octet, il n'y a pas d'intermédiaire avec des chaines de caractères. Pas besoin de fonction comme LEFT,INSTR,..., rien du tout. La valeur stocké dans la mémoire tampon est copié directement dans la variable utilisateur. Précaution à prendre : si on modifie un octet qui est en dehors de la mémoire tampon, on déclenche le mécanisme de protection de Windows, à savoir le fameux "ACCESS VIOLATION", donc être rigoureux quant on code En exemple, "GetCursorPos" de la DLL user32: - Code:
-
' Panoramic 0.9.25
' ============================================================== ' = Title : GetCursorPos ' = ' = Author : Silverman ' = ' = Date : Avril 2015 ' = ' = Version: 1.1 ' ============================================================== ' Comments : Créer une mémoire tampon pour DLL. ' : Exemple avec la fonction User32 : GetCursorPos ' ==============================================================
' Attention au type de données:( plus d'info ici : https://msdn.microsoft.com/en-us/library/cc230318.aspx ) ' ' LONG = 4 bytes ---> entier signé, donc la variable de stockage d'un LONG se termine par %(x%,y%,...) ' ' pointeur : DWORD ' DWORD=4 bytes non signé; ce type n'existe pas en Panoramic, mais on peut le remplacer par ' un LONG à condition qu'il soit toujours positif. Ex. de DWORD: lpPoint_ptr% ' ' lpPoint$ = structure POINT; détail ici : https://msdn.microsoft.com/fr-fr/library/windows/desktop/dd162805%28v=vs.85%29.aspx ' ' les valeurs retournées dans la structure POINT sont : 2 LONG ' ' GetCursorPos; détail ici : https://msdn.microsoft.com/fr-fr/library/windows/desktop/ms648390%28v=vs.85%29.aspx
' NB: si on essaye de lire des données en deçà ou au-delà de la taille du buffer que l'on à créé, il y a le risque de déclencher ' le système de protection de WINDOWS, à savoir le célèbre... "ACCESS VIOLATION". '
' données pour le buffer dim lpPoint$ dim lpPoint_ptr%
' créer un buffer pour 2 LONG(donc 8 bytes) nuls lpPoint$=string$(8,chr$(0))
' copie le CONTENU de adr(lpPoint$), dans lpPoint_ptr%.(NB: Le contenu de adr(lpPoint$) est l'adresse réelle du buffer) GET_BUFFER_PTR(adr(lpPoint_ptr%),adr(lpPoint$))
' données pour la démo dim bool dim x% dim y%
alpha 1
dll_on "user32"
repeat ' bool retourne une valeur non nulle si l'appel à la fonction est un succès; pas utile ici. ' ATTENTION !! il faut tenir compte de la casse. "GetCursorPos"--->ok , "getcursorpos"--->erreur bool=dll_call1("GetCursorPos",lpPoint_ptr%)
' copie les valeurs des coordonnées souris contenu dans le buffer, dans les variables x% et y% READ_BUFFER_LONG(adr(x%),lpPoint_ptr%,0) READ_BUFFER_LONG(adr(y%),lpPoint_ptr%,4)
' affichage du résultat caption 1,"X = "+str$(x%)+" Y = "+str$(y%)
until scancode<>0
END sub READ_BUFFER_LONG(adr_destination%,adr_source%,buffer_position%) ' LONG = 4 BYTEs ' adr_destination% = adresse destination ' adr_source% = adresse adr_source ' copie un LONG, –2147483648 < LONG < 2147483647 poke adr_destination%,peek(adr_source%+buffer_position%) poke adr_destination%+1,peek(adr_source%+1+buffer_position%) poke adr_destination%+2,peek(adr_source%+2+buffer_position%) poke adr_destination%+3,peek(adr_source%+3+buffer_position%) end_sub
sub GET_BUFFER_PTR(adr_destination%,adr_source%) ' retrouve l'adresse du pointeur poke adr_destination%,peek(adr_source%) poke adr_destination%+1,peek(adr_source%+1) poke adr_destination%+2,peek(adr_source%+2) poke adr_destination%+3,peek(adr_source%+3) end_sub
Dernière édition par silverman le Lun 27 Avr 2015 - 13:25, édité 11 fois | |
| | | Jicehel
Nombre de messages : 5947 Age : 52 Localisation : 77500 Date d'inscription : 18/04/2011
| Sujet: Re: Astuce : créer mémoire tampon(très utile pour CALL_DLLx()) Sam 25 Avr 2015 - 18:51 | |
| Si, ça a déjà était indiqué par Klaus, mais ça ne retire rien au fait que ce soit bien de le partager proprement comme dans ton post. Ce genre d'astuces est toujours bonne à rappeler car ce n'est pas du tout inné ou facile à trouver. De plus Klaus utilisait la chaine de caractères et pas les pokes, ton approche est donc très interssante | |
| | | papydall
Nombre de messages : 7017 Age : 74 Localisation : Moknine (Tunisie) Entre la chaise et le clavier Date d'inscription : 03/03/2012
| Sujet: Re: Astuce : créer mémoire tampon(très utile pour CALL_DLLx()) Sam 25 Avr 2015 - 19:04 | |
| Je pense qu’on est devant deux approches différentes : celle de klaus et celle (très astucieuse) de Silverman. Merci pour le partage, silverman. | |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: Astuce : créer mémoire tampon(très utile pour CALL_DLLx()) Sam 25 Avr 2015 - 19:06 | |
| Ce que je préconise, habituellement, pour les fonctions de KGF.dll qui retournent une chaine de caractères, c'est de faire une chaîne par s$=string$(255," "). 255 est bien sûr juste un exemple. Ensuite, on passe adr(s$) en paramètre à la fonction. Et pour finir, on fait s$=trim$(s$). Comment ça marche ? Mes fonctions copient du texte dans la zone mémoire pointée par adr(s$), et arrête la copie lorsque la première des deux conditions suivantes survient: 1. il n'y a plus de caractères à copier 2. l'octet en mémoire censé recevoir le prochain caractère est un NULL (zéro binaire). La condition (2) est la sécurité pour éviter d'écrire au-delà de l'espace alloué à une variable de type chaîne de caractères. Les données de telles variables Panoramic sont toujours terminées par un octet NULL. Donc, si tu crées une chaîne par s$=string$(255,chr$(0)), tu n'obtiendras jamais les données que la fonction doit retourner, car dès le premier caractère, elle va tomber sur un octet NULL et arrête la copie. Pour résumer, ce qu'il faut faire: - Code:
-
dim s$, res% s$ = string$(300," ") res% = dll_callx("MaFonction",...,adr(s$),...) s$ = trim$(s$) Bien entendu, cette réflexion n'est valable que pour un appel à des fonctions de KGF.dll. Pour un appel d'autres DLLs comme User32.dll etc, la technique faisant l'objet de post est parfaitement applicable. | |
| | | Nardo26
Nombre de messages : 2294 Age : 56 Localisation : Valence Date d'inscription : 02/07/2010
| Sujet: Re: Astuce : créer mémoire tampon(très utile pour CALL_DLLx()) Sam 25 Avr 2015 - 20:00 | |
| L'ideal serait d'avoir l'adresse exacte où se trouve par exemple les données d'un tableau d'entier. C'est cette adresse là qu'il faudrait passer en parametre : les données seraient de suite dispo en Panoramic. On avait déjà prospecté dans ce sens là : https://panoramic.1fr1.net/t2572-pic-et-poc-les-joyeux-drillesMais apparemment, les structures ont évoluées... (ou la fonction ADR a été retravaillée : les progs qui marchaient avant, ne fonctionnent plus) | |
| | | silverman
Nombre de messages : 970 Age : 52 Localisation : Picardie Date d'inscription : 18/03/2015
| Sujet: Re: Astuce : créer mémoire tampon(très utile pour CALL_DLLx()) Sam 25 Avr 2015 - 21:13 | |
| @Nardo26 vraiment très intéressant ce lien, je ne l'avais pas trouvé dans mes recherches sur peek.
@Klaus je suis habitué à créer des mémoires tampon de taille fixe, et par défaut elles sont initialisées avec des 0. C'est la façon de procéder pour utiliser les dlls windows. C'est la première fois que je vois une mémoire tampon initialisé avec la valeur 32, et ça me déroute. Je n'ai pas du tout saisi les explication que tu as données; aurait tu un code très court pour que je puisse tester? | |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: Astuce : créer mémoire tampon(très utile pour CALL_DLLx()) Dim 26 Avr 2015 - 1:03 | |
| Facile ! Prenons ma fonction qui retourne la version de KGF.dll. Elle retourne une valeur numérique comme résultat de la fonction, et une chaine de caractères de 25 caractères de long, pour la description textuelle: - Code:
-
dim vers$, vers%
dll_on "KGF.dll"
vers$ = string$(40,chr$(0)) vers% = DLL_call1("KGFdllVersion", adr(vers$) ) message str$(vers%)+" correspond à "+vers$
vers$ = string$(40," ") vers% = DLL_call1("KGFdllVersion", adr(vers$) ) vers$ = trim$(vers$) message str$(vers%)+" correspond à "+vers$
Tu verras aisément la différence de comportement... | |
| | | Nardo26
Nombre de messages : 2294 Age : 56 Localisation : Valence Date d'inscription : 02/07/2010
| Sujet: Re: Astuce : créer mémoire tampon(très utile pour CALL_DLLx()) Dim 26 Avr 2015 - 1:13 | |
| Tu as raison Klaus, mais cela marche pour des appels a des fct de ta DLL. (car tu intègres le pointeur de chaine) @Silverman : J'ai pas d'exemple sous le coude mais l'utilisation d'une chaine de caractères en tant que buffer pour une DLL système pose problème. En effet, la fct ADR() ne te renvoie pas l'adresse de la zone mémoire qui contient la chaine de caractères mais elle te donne un pointeur sur cette adresse. Donc une petite manipulation s'impose avant de pouvoir passer une adresse de buffer : - Code:
-
DIM buffer$ DIM ptr%,ret% DIM i
buffer$="Exemple de buffer pour appel à une fct d'une DLL système" ptr%=adr(buffer$) dll_on "kernel32.dll" ' on récupère le pointeur sur la chaine de caractères et on le stocke dans la variable ptr% ret%=DLL_CALL3("RtlMoveMemory",adr(ptr%),ptr%,4) dll_off ' A partir de là, ptr% contient la véritable adresse où débute la chaine de caractères (le buffer). ' tu peux y mettre ce que tu veux, à l'aide de POKE en faisant attention de ne pas déborder bien sur...
' exemple: on récupère le contenu du "buffer" à l'aide de peek FOR i=0 TO LEN(buffer$)-1 PRINT CHR$(PEEK(ptr%+i)); NEXT i
Maintenant le contenu initial de la chaine importe peu car c'est à toi d'y mettre les données nécessaires... | |
| | | Jicehel
Nombre de messages : 5947 Age : 52 Localisation : 77500 Date d'inscription : 18/04/2011
| Sujet: Re: Astuce : créer mémoire tampon(très utile pour CALL_DLLx()) Dim 26 Avr 2015 - 10:29 | |
| Voir l'autre poste où Nardo donne les fonctions pour remplir la chaine de caractères simplement | |
| | | silverman
Nombre de messages : 970 Age : 52 Localisation : Picardie Date d'inscription : 18/03/2015
| Sujet: Re: Astuce : créer mémoire tampon(très utile pour CALL_DLLx()) Dim 26 Avr 2015 - 11:58 | |
| @KlausMerci, j'essaye ça. @Nardo26 - Nardo26 a écrit:
En effet, la fct ADR() ne te renvoie pas l'adresse de la zone mémoire qui contient la chaine de caractères mais elle te donne un pointeur sur cette adresse.
Tout à fait, et je lis ce pointeur d'adresse avec la sub GET_BUFFER_PTR(sub qui recopie cette adresse dans une variable utilisateur), et c'est ce que tu fais avec "RtlMoveMemory". Je n'ai pas utilisé "RtlMoveMemory" du kernel32 pour les copies mémoires car on ne peut utiliser qu'une seule dll à la fois, c'est pour ça que je l'ai fait en Panoramic pur. - silverman a écrit:
- récupérer le pointeur de cette chaine, pointeur qui pointe sur un second pointeur
mais je me rend compte que cette explication est confuse, j'ai édité mon premier post pour corriger cela. L'idée de créer une mémoire tampon m'est venu à la suite d'un post dans lequel je met un code utilisant user32. On peut le trouver ici, tout en bas de la page: https://panoramic.1fr1.net/t3520-re-tout-le-monde-dJ'avais solutionné le probleme en utilisant la fonction "SetCursorPos". A la suite de quoi, des liens vers qq fonctions des dlls windows ont été postés. Mais sans mémoire tampon, on ne peut pas en utiliser beaucoup. Cette astuce permet aux Panoramicien(ne)s de "bidouiller" avec les dlls systèmes.(Testeur fou, à vos clavier! )
Dernière édition par silverman le Lun 27 Avr 2015 - 13:51, édité 1 fois | |
| | | Jicehel
Nombre de messages : 5947 Age : 52 Localisation : 77500 Date d'inscription : 18/04/2011
| Sujet: Re: Astuce : créer mémoire tampon(très utile pour CALL_DLLx()) Dim 26 Avr 2015 - 15:31 | |
| Absolument on a de quoi faire avec ces différentes méthodes | |
| | | Nardo26
Nombre de messages : 2294 Age : 56 Localisation : Valence Date d'inscription : 02/07/2010
| Sujet: Re: Astuce : créer mémoire tampon(très utile pour CALL_DLLx()) Dim 26 Avr 2015 - 17:01 | |
| - silverman a écrit:
- [...]Mais sans mémoire tampon, on ne peut pas en utiliser beaucoup.
Sans compter qu'il faut aussi que la fct renvoie une valeur booléenne... | |
| | | Contenu sponsorisé
| Sujet: Re: Astuce : créer mémoire tampon(très utile pour CALL_DLLx()) | |
| |
| | | | Astuce : créer mémoire tampon(très utile pour CALL_DLLx()) | |
|
Sujets similaires | |
|
| Permission de ce forum: | Vous ne pouvez pas répondre aux sujets dans ce forum
| |
| |
| |