OVH Cloud OVH Cloud

[WD7.5 204g] Allocation de mémoire

12 réponses
Avatar
Philippe
Salut,

Je fais une fonction dans ma dll équivalente au fChargeTexte() de Windev,
mon problème est l'allocation de la variable sous Windev pour récupérer le
résultat de la dll.

gFile is string="F:\monfichier.txt"+caract(0)
gString is string=Repete(" ",ftaille(gFile))+caract(0)
API("Madll","MaFonction", &gFile, &gString)
Info(gString)

Comment faire autrement que part le Repete(" ", fTaille(MonFichier)) ?

Si je mets juste gString=caract(0) à partir d'une certaine taille j'ai un
débordement de buffer.

j'ai le même résultat si je m'amuse avec une allocation sur le tas du type
HeapAlloc() et Transfert() de Windev après, il lui faut une chaine fixe.

Une idée ...

A+
Philippe

10 réponses

1 2
Avatar
Philippe
Merci,

Le problème est que l'appel de ma fonction se situe dans une classe et il
refuse de compiler le code.

Sinon tu penses que l'allocation dynamique du tableau est + rapide la
construction d'une chaine fixe ?

A+
Philippe

"Pierre-Yves Tavernier" a écrit dans le
message de news:3f36ab86$0$16525$
Bonsoir,

:Fabrice Burghgraeve a donné un bonne exemple sur ce forum :

FONCTION get_info_imprimante(hPrinter est un entier, info_imp est un
struct_PRINTER_INFO_2A, buffer)
// revoit vrai ou faux suivant que les information ont pu etre lues ou


pas.
// hPrinter : handle de l'imprimante
// buffer doit etre declare en tableau dynamique dans la fonction


appelante.
// ATTENTION A BIEN DESALLOUER LE BUFFER QUAND ON N'EN A PLUS BESOIN

cByteNeeded,cByteUsed est un entier
AppelDLL32("winspool.drv","GetPrinterA",hPrinter,INFO_LEVEL_2,Null,0,
&cByteNeeded)
SI cByteNeeded=0 ALORS RENVOYER Faux
buffer = allouer un tableau dynamique de (cByteNeeded+1) caractères
SI PAS AppelDLL32("winspool.drv","GetPrinterA", hPrinter, INFO_LEVEL_2,
&buffer, cByteNeeded, &cByteUsed) ALORS
Info(ErreurInfo())
AppelDLL32("winspool.drv","ClosePrinter",hPrinter)
libérer(buffer)
RENVOYER Faux
FIN
Transfert(&info_imp,&buffer,SIZE_STRUCT_PRINTER_INFO_2A);
RENVOYER Vrai


PYT

"Philippe" a écrit dans le message de news:
_JxZa.29916$
> Salut,
>
> Je fais une fonction dans ma dll équivalente au fChargeTexte() de


Windev,
> mon problème est l'allocation de la variable sous Windev pour récupérer


le
> résultat de la dll.
>
> gFile is string="F:monfichier.txt"+caract(0)
> gString is string=Repete(" ",ftaille(gFile))+caract(0)
> API("Madll","MaFonction", &gFile, &gString)
> Info(gString)
>
> Comment faire autrement que part le Repete(" ", fTaille(MonFichier)) ?
>
> Si je mets juste gStringÊract(0) à partir d'une certaine taille j'ai


un
> débordement de buffer.
>
> j'ai le même résultat si je m'amuse avec une allocation sur le tas du


type
> HeapAlloc() et Transfert() de Windev après, il lui faut une chaine fixe.
>
> Une idée ...
>
> A+
> Philippe
>
>




Avatar
Philippe
Merci,

La méthode Repete produit de meilleur résultats. Sur un fichier de 300 Ko
l'affection par charactère fait perdre les pédales au programme :)
Chrono en main ma fonction est + rapide que le fChargeTexte() de PCM !

A+
Philippe

"Pierre-Yves Tavernier" a écrit dans le
message de news:3f36b1c3$0$16547$
Si tu veux utiliserr HeapAlloc, il faut faire comme dans l'exemple si
dessous :

*****Ouverture de la fenêtre LInfo

global
LOCALE_USER_DEFAULT est un entier long = 0x400

NO_ERROR est un entier long = 0
LOCALE_SDATE est un entier long = 29
LOCALE_SSHORTDATE est un entier long = 31

***** Procédure GetLocaleInfo
Procédure GetMocalInfo(typeInfo,resultat)

buffer est un entier long = NULL
needed est une entier long
memoNeeded est un entier long
lastError est un entier long
car est un caractere
i est un entier long

needed = AppelDLL32("kernel32","GetLocaleInfoA" ,...
LOCALE_USER_DEFAULT,...
typeInfo,...
buffer,...
0)

lastError = AppelDLL32("kernel32","GetLastError" )

si lastError = NO_ERROR alors
buffer = AppelDLL32("kernel32","GlobalAlloc" , NULL, needed)
lastError = AppelDLL32("kernel32","GetLastError" )
fin

si lastError = NO_ERROR alors
needed = AppelDLL32("kernel32","GetLocaleInfoA" ,...
LOCALE_USER_DEFAULT,...
typeInfo,...
buffer,...
needed)
memoNeeded = needed-2
lastError = AppelDLL32("kernel32","GetLastError" )
FIN

si lastError = NO_ERROR alors
resultat = ""
pour i=0 à memoNeeded
transfert(&car,buffer+i,1)
resultat += car
FIN
FIN

si lastError <> NO_ERROR alors
resultat = "Erreur n° "+lastError
FIN

si buffer <> NULL alors
AppelDLL32("kernel32","GlobalFree" , buffer)
fin

renvoyer lastError



PYT
"Philippe" a écrit dans le message de news:
69yZa.30179$
> Merci,
>
> Le problème est que l'appel de ma fonction se situe dans une classe et


il
> refuse de compiler le code.
>
> Sinon tu penses que l'allocation dynamique du tableau est + rapide la
> construction d'une chaine fixe ?
>
> A+
> Philippe
>
> "Pierre-Yves Tavernier" a écrit dans le
> message de news:3f36ab86$0$16525$
> > Bonsoir,
> >
> > :Fabrice Burghgraeve a donné un bonne exemple sur ce forum :
> >
> > FONCTION get_info_imprimante(hPrinter est un entier, info_imp est un
> > struct_PRINTER_INFO_2A, buffer)
> > // revoit vrai ou faux suivant que les information ont pu etre lues ou
> pas.
> > // hPrinter : handle de l'imprimante
> > // buffer doit etre declare en tableau dynamique dans la fonction
> appelante.
> > // ATTENTION A BIEN DESALLOUER LE BUFFER QUAND ON N'EN A PLUS BESOIN
> >
> > cByteNeeded,cByteUsed est un entier
> > AppelDLL32("winspool.drv","GetPrinterA",hPrinter,INFO_LEVEL_2,Null,0,
> > &cByteNeeded)
> > SI cByteNeeded=0 ALORS RENVOYER Faux
> > buffer = allouer un tableau dynamique de (cByteNeeded+1) caractères
> > SI PAS AppelDLL32("winspool.drv","GetPrinterA", hPrinter,


INFO_LEVEL_2,
> > &buffer, cByteNeeded, &cByteUsed) ALORS
> > Info(ErreurInfo())
> > AppelDLL32("winspool.drv","ClosePrinter",hPrinter)
> > libérer(buffer)
> > RENVOYER Faux
> > FIN
> > Transfert(&info_imp,&buffer,SIZE_STRUCT_PRINTER_INFO_2A);
> > RENVOYER Vrai
> >
> >
> > PYT
> >
> > "Philippe" a écrit dans le message de news:
> > _JxZa.29916$
> > > Salut,
> > >
> > > Je fais une fonction dans ma dll équivalente au fChargeTexte() de
> Windev,
> > > mon problème est l'allocation de la variable sous Windev pour
récupérer
> le
> > > résultat de la dll.
> > >
> > > gFile is string="F:monfichier.txt"+caract(0)
> > > gString is string=Repete(" ",ftaille(gFile))+caract(0)
> > > API("Madll","MaFonction", &gFile, &gString)
> > > Info(gString)
> > >
> > > Comment faire autrement que part le Repete(" ", fTaille(MonFichier))


?
> > >
> > > Si je mets juste gStringÊract(0) à partir d'une certaine taille


j'ai
> un
> > > débordement de buffer.
> > >
> > > j'ai le même résultat si je m'amuse avec une allocation sur le tas


du
> type
> > > HeapAlloc() et Transfert() de Windev après, il lui faut une chaine
fixe.
> > >
> > > Une idée ...
> > >
> > > A+
> > > Philippe
> > >
> > >
> >
> >
>
>




Avatar
Philippe
> qu'est ce que tu veux dire par la ?



Le programme ne réponds +, ce qui semble logique car si on fait 300*1024
soit 307200 appels à la fonction Transfert() y'a de quoi se pommer les ....

tu peux donner ton bout de code avec les tableau et sans ?



Avec le tableau cf. le code PYT ci-dessous, sans le tableau un simple
Repete():

cString is string=RepeatString(" ",:Size(cFileName))+Caract(0)
API(:cDll,::_PRA_pLoadText, &cFileName, &cString)
RESULT cString

Le remplissage de cString est fait par ma dll

A+
Philippe


"Fabrice Burghgraeve" a
écrit dans le message de news:bhaip1$1a3$
salut.

"Philippe" a écrit dans le message de
news:WVQZa.46223$
> Merci,
>
> La méthode Repete produit de meilleur résultats. Sur un fichier de 300


Ko
> l'affection par charactère fait perdre les pédales au programme :)

qu'est ce que tu veux dire par la ?

parce qu'en utilisant repete et transfert pour les appels aux APIs, je te
garantis un gros risque de problemes. (eventuelement d'apparence


aleatoire)

que veux-tu dire par "perdre les pedales" ?

j'avais jamais essaye un tableau de 300 Ko, mais theoriquement, ca doit
aller.
En tout cas, il n'y a pas de limite de taille donnee dans la partie


limites
de l'aide sur les tableaux, et dans la partie "limites de windev", il est
dit que la taille du tableau est limitee par la memoire disponible...

tu peux donner ton bout de code avec les tableau et sans ?

> Chrono en main ma fonction est + rapide que le fChargeTexte() de PCM !
>
> A+
> Philippe
>
(...)




Avatar
PYT
Voici un extrait de l'aide windev 75204g sur la fonction API:

Les types "chaîne". Pour transmettre une chaîne à une fonction, il est possible
d'utiliser le type "Chaîne". Le type "Chaîne ASCIIZ" doit être utilisé pour
récupérer le résultat d'une fonction.

Alors vigilence avec les chaines...

Dans le code avec le transfert : ce n'est pas le transfert qui perturbe mais les
multiples allocations réallocation générés lors de la concaténation du caractère.
A priori, le type chaine est un type dynamique qui se réalloc automatiquement
quand la taille s'agrandi. Un peu comme les string de la stl du C++. Et c'est
pour cela qu'il ne faut pas l'affecter aux travers d'API externe à WIndev.

PYT

--
Ce message a été posté via la plateforme Web club-Internet.fr
This message has been posted by the Web platform club-Internet.fr

http://forums.club-internet.fr/
Avatar
Fabrice Burghgraeve
salut.

"Philippe" a écrit dans le message de
news:mD5_a.63156$

> qu'est ce que tu veux dire par la ?

Le programme ne réponds +, ce qui semble logique car si on fait 300*1024
soit 307200 appels à la fonction Transfert() y'a de quoi se pommer les


....

je comprends plus rien, la...
j'ai du rater le bout de code dans les differents quotages, ou il y a un
probleme de synchro avec les serveurs de news...

pourquoi 300 * 1024 fois la fonctions transfert ?????


> tu peux donner ton bout de code avec les tableau et sans ?

Avec le tableau cf. le code PYT ci-dessous, sans le tableau un simple
Repete():

cString is string=RepeatString(" ",:Size(cFileName))+Caract(0)
API(:cDll,::_PRA_pLoadText, &cFileName, &cString)
RESULT cString




j'ai beau regarder, je vois pas de tableau dynamique de caracteres la
dedans...

Le remplissage de cString est fait par ma dll

A+
Philippe





--
Fabrice Burghgraeve
Computer & Services

(enlevez le _pas_de_spam_ pour me répondre en privé)

P.S. : essaye de faire un ch'ti n'effort pour quoter mieux que ca, ca
aiderait...
Avatar
Philippe
Dans le dernier message de PYT on parlait d'un grossissement dynamique de la
chaîne (+=) en faisant un transfert char / char du buffer allouer sur le tas
(HeapAlloc()...). Soit si tu as un fichier de 300Ko 300*1024 char donc
307200 appels à la fonction transfert puis += pour récupérer la valeur dans
une chaîne.
C'est çà que le programme n'aimes pas !!!
L'utilisation d'un tableau dynamique est autre chose, mais comme ma fonction
est dans une classe cela ne marches pas. D'autre part le passage d'un
tableau par adresse à une dll ne marches pas non plus.

L'utilisation de répète pour allouer l'espace suffisant donnes de bon
résultat sur des fichiers de taille <raisonnable>.


"Fabrice Burghgraeve" a
écrit dans le message de news:bhapkb$6dh$
salut.

"Philippe" a écrit dans le message de
news:mD5_a.63156$
>
> > qu'est ce que tu veux dire par la ?
>
> Le programme ne réponds +, ce qui semble logique car si on fait 300*1024
> soit 307200 appels à la fonction Transfert() y'a de quoi se pommer les
....

je comprends plus rien, la...
j'ai du rater le bout de code dans les differents quotages, ou il y a un
probleme de synchro avec les serveurs de news...

pourquoi 300 * 1024 fois la fonctions transfert ?????

>
> > tu peux donner ton bout de code avec les tableau et sans ?
>
> Avec le tableau cf. le code PYT ci-dessous, sans le tableau un simple
> Repete():
>
> cString is string=RepeatString(" ",:Size(cFileName))+Caract(0)
> API(:cDll,::_PRA_pLoadText, &cFileName, &cString)
> RESULT cString
>

j'ai beau regarder, je vois pas de tableau dynamique de caracteres la
dedans...

> Le remplissage de cString est fait par ma dll
>
> A+
> Philippe
>


--
Fabrice Burghgraeve
Computer & Services

(enlevez le _pas_de_spam_ pour me répondre en privé)

P.S. : essaye de faire un ch'ti n'effort pour quoter mieux que ca, ca
aiderait...




Avatar
Fabrice Burghgraeve
salut.

"Philippe" a écrit dans le message de
news:So6_a.64225$
Dans le dernier message de PYT on parlait d'un grossissement dynamique de


la
chaîne (+=) en faisant un transfert char / char du buffer allouer sur le


tas
(HeapAlloc()...). Soit si tu as un fichier de 300Ko 300*1024 char donc
307200 appels à la fonction transfert puis += pour récupérer la valeur


dans
une chaîne.
C'est çà que le programme n'aimes pas !!!



!!!!!
Mais on fait *JAMAIS* ca...
!!!!!
quand on fait un "grossissement dynamique", deja, on n'alloue jamais
caractere par caractere, mais plutot par bloc, pour limiter le nombre
d'allocations... specialement si il y a un gros volume de donnees.

en plus, pour agrandir la taille d'un buffer, on n'utilise pas un malloc (je
pense que c'est equivalent a Heapalloc) mais realloc...


L'utilisation d'un tableau dynamique est autre chose, mais comme ma


fonction
est dans une classe cela ne marches pas.



qu'est ce qui ne marche pas ?

D'autre part le passage d'un
tableau par adresse à une dll ne marches pas non plus.



bien sur que si ca marche...
Le code qu'a donné PYT qui vient de moi fonctionne et utilise ca...

L'utilisation de répète pour allouer l'espace suffisant donnes de bon
résultat sur des fichiers de taille <raisonnable>.



Oui oui...
Sauf que ca deconne ca je te le garantis....
C'est d'ailleurs pour ca que j'ai trouve cette astuce du tableau dynamique
de caracteres, parce que ca deconnait justement avec un exemple de PCSOFT
qui servait a lister les imprimantes.
Mais j'ai deja constate que ca deconne avec d'autres appels aux DLLs...
(carte vitale)

Fais comme tu veux, mais le type string n'est vraiment pas le bon type pour
les appels aux DLLs

--
Fabrice Burghgraeve
Computer & Services

(enlevez le _pas_de_spam_ pour me répondre en privé)
Avatar
Philippe
> Mais on fait *JAMAIS* ça...



Je sais bien, c'est pour cela que je ne le fait pas...

quand on fait un "grossissement dynamique", déjà, on n'alloue jamais
caractère par caractère, mais plutôt par bloc, pour limiter le nombre
d'allocations... spécialement si il y a un gros volume de données.



Là j'ai pas les sources de PCM :) mais vu la lenteur de certaines fonctions,
je me pose des questions :) (oups, désolé)

en plus, pour agrandir la taille d'un buffer, on n'utilise pas un malloc


(je
pense que c'est équivalent a Heapalloc) mais realloc...



Là je sais aussi mais on parle de "grossissement" Windev pas de C++, donc
quand leur routine détecte qu'elle n'a + assez de place dans la "string" ils
doivent réallouent un bloc, c'était mon sens de "grossissement dynamique"

qu'est ce qui ne marche pas ?



Tu ne peux pas déclarer un <tableau dynamique sur x char> la compilation est
refusée

bien sur que si ça marche...
Le code qu'a donné PYT qui vient de moi fonctionne et utilise ça...



S'cuses pour moi, c'est dû à l'erreur précédente dans la méthode de classe

Fais comme tu veux, mais le type string n'est vraiment pas le bon type


pour
les appels aux DLLs



Ben là j'ai pas le même résultat, mais comme c'est moi qui fait les dll que
j'utilisent je maîtrise les deux cotés de la chose.
Une chaîne asciiz ou une (chaîne+caract(0)) produit exactement les mêmes
résultats. Si ta fonction dans une dll attend un (char*) alors tu passe une
chaîne +'' par adresse et cela ne pose aucun problèmes. Après si tu fais
appel à des API Windows ou autre sans savoir exactement comment est traitée
la donnée et exactement quelle est le type de données en entrée de la dll
alors oui çà peut poser des problèmes.

A+
Philippe

"Fabrice Burghgraeve" a
écrit dans le message de news:bhasuf$7mc$
salut.

"Philippe" a écrit dans le message de
news:So6_a.64225$
> Dans le dernier message de PYT on parlait d'un grossissement dynamique


de
la
> chaîne (+=) en faisant un transfert char / char du buffer allouer sur le
tas
> (HeapAlloc()...). Soit si tu as un fichier de 300Ko 300*1024 char donc
> 307200 appels à la fonction transfert puis += pour récupérer la valeur
dans
> une chaîne.
> C'est çà que le programme n'aimes pas !!!

!!!!!
Mais on fait *JAMAIS* ca...
!!!!!
quand on fait un "grossissement dynamique", deja, on n'alloue jamais
caractere par caractere, mais plutot par bloc, pour limiter le nombre
d'allocations... specialement si il y a un gros volume de donnees.

en plus, pour agrandir la taille d'un buffer, on n'utilise pas un malloc


(je
pense que c'est equivalent a Heapalloc) mais realloc...


> L'utilisation d'un tableau dynamique est autre chose, mais comme ma
fonction
> est dans une classe cela ne marches pas.

qu'est ce qui ne marche pas ?

>D'autre part le passage d'un
> tableau par adresse à une dll ne marches pas non plus.

bien sur que si ca marche...
Le code qu'a donné PYT qui vient de moi fonctionne et utilise ca...

> L'utilisation de répète pour allouer l'espace suffisant donnes de bon
> résultat sur des fichiers de taille <raisonnable>.

Oui oui...
Sauf que ca deconne ca je te le garantis....
C'est d'ailleurs pour ca que j'ai trouve cette astuce du tableau dynamique
de caracteres, parce que ca deconnait justement avec un exemple de PCSOFT
qui servait a lister les imprimantes.
Mais j'ai deja constate que ca deconne avec d'autres appels aux DLLs...
(carte vitale)

Fais comme tu veux, mais le type string n'est vraiment pas le bon type


pour
les appels aux DLLs

--
Fabrice Burghgraeve
Computer & Services

(enlevez le _pas_de_spam_ pour me répondre en privé)




Avatar
Pierre-Yves Tavernier
">
Ben là j'ai pas le même résultat, mais comme c'est moi qui fait les dll


que
j'utilisent je maîtrise les deux cotés de la chose.
Une chaîne asciiz ou une (chaîne+caract(0)) produit exactement les mêmes
résultats. Si ta fonction dans une dll attend un (char*) alors tu passe


une
chaîne +'' par adresse et cela ne pose aucun problèmes. Après si tu fais
appel à des API Windows ou autre sans savoir exactement comment est


traitée
la donnée et exactement quelle est le type de données en entrée de la dll
alors oui çà peut poser des problèmes.



Je te remets un extrait d'un post que tu n'as pas du lire

Voici un extrait de l'aide windev 75204g sur la fonction API:

Les types "chaîne". Pour transmettre une chaîne à une fonction, il est
possible
d'utiliser le type "Chaîne". Le type "Chaîne ASCIIZ" doit être utilisé pour
récupérer le résultat d'une fonction.


PYT
Avatar
Philippe
Ben là ils ont tord, parce que je le fait depuis des mois avec mon
application (Mp3Tools) et aucun problèmes signalé !
Simplement si la dll attend une REG_SZ il faut ajouter un caract(0), si elle
attend une MULTI_SZ faut rajouter 2 caract(0).
Maintenant je ne fais + confiance à l'aide et aux fonctions de PCM, surtout
lors des MAJ, c'est pourquoi maintenant j'implémente & substitue petit à
petit toutes les fonctions dont j'ai besoin, même les + basiques avec celle
de ma dll. Comme çà si çà bug je sais à qui m'adresser, à moi :) et là je
suis sur d'obtenir une réponse, la mienne :)

A+
Philippe

"Pierre-Yves Tavernier" a écrit dans le
message de news:3f394d65$0$1112$

">
> Ben là j'ai pas le même résultat, mais comme c'est moi qui fait les dll
que
> j'utilisent je maîtrise les deux cotés de la chose.
> Une chaîne asciiz ou une (chaîne+caract(0)) produit exactement les mêmes
> résultats. Si ta fonction dans une dll attend un (char*) alors tu passe
une
> chaîne +'' par adresse et cela ne pose aucun problèmes. Après si tu


fais
> appel à des API Windows ou autre sans savoir exactement comment est
traitée
> la donnée et exactement quelle est le type de données en entrée de la


dll
> alors oui çà peut poser des problèmes.
>
Je te remets un extrait d'un post que tu n'as pas du lire

Voici un extrait de l'aide windev 75204g sur la fonction API:

Les types "chaîne". Pour transmettre une chaîne à une fonction, il est
possible
d'utiliser le type "Chaîne". Le type "Chaîne ASCIIZ" doit être utilisé


pour
récupérer le résultat d'une fonction.


PYT







1 2