J'ai pas senti sur le forum anglais une envie de t'aider de la part de Fred/Freak.
J'ai regardé mais avec le pointeur du gadget de PB je n'arrive à rien.
Pour le code asm posté par Gnozal, voici ce que je comprend
Code : Tout sélectionner
!EXTRN _PB_GetGadgetItemText2@16
;
!MOV Eax,[_PB_StringBasePosition]
!PUSH Eax
!PUSH Eax
!PUSH dword 1 ; colonne
!PUSH dword 0 ; ligne
!PUSH dword 10 ; gadget
!CALL _PB_GetGadgetItemText2@16
!LEA Ecx,[v_a$] ; variable
!POP Edx
!CALL SYS_AllocateString
La fonction appelée est _PB_GetGadgetItemText2@16 qui a donc 4 paramètres Long (4 x 4 = 16, qui correspond au 16 après le @) alors que la fonction PB accepte au plus 3 paramètres (3 x 4 = 12). De toute évidence il y a plusieurs fonctions GetGadgetItemText car celle-ci se fini par 2 (_PB_GetGadgetItemText2), ce qui fait que je ne sais pas vraiment sur quoi pointe *g\VT\GetGadgetItemText, peut-être une table (?) donc sans explication, on arrive pas à grand chose. L'utilisation des autres fonctions GetGadgetItemText (avec un nombre de paramètres différent) dépend peut-être du contexte tel que décrit dans le SDK ci-dessous.
Pour revenir au code asm, le premier Push eax est fait pour mémoriser le pointeur _PB_StringBasePosition qui donne le pense le début de la zone libre du buffer d'écriture des chaînes (mais bon ?), cette valeur est récupére par le POP edx.
Le deuxième PUSH eax (on empile le pointeur _PB_StringBasePosition) est un des paramètre de la fonction _PB_GetGadgetItemText2@16, les autre PUSH correspondent comme Gnozal l'a écrit aux paramètres propres de la fonction. PB va utiliser le pointeur pour écrire la chaîne dans le buffer (enfin je pense) et ce pointeur aura ensuite une valeur différente d'avant l'appel de la fonction. Mais comme on a empilé la valeur initiale, c'est cette valeur qui pointera le début de la chaine écrite sur le buffer.
Ensuite, pour attribuer à la variable a$ le contenu de la chaine lue, PB va allouer de la mémoire pour cette opération en utilisant l'appel de fonction !CALL SYS_AllocateString qui admet deux paramètres :
ECX reçoit l'adresse de la variable a$, qu'elle soit locale ou globale
EDX récupère le pointeur _PB_StringBasePosition avant écriture du buffer
La fonction admet je pense un troisième paramètre qui est masqué qui est la taille de la chaine retournée dans eax par le CALL _PB_GetGadgetItemText2@16
C'est que j'ai compris mais c'est comme tout, beaucoup d'incertitudes
Pour que tout soit clean, il faut ensuite détruire la mémoire attribuée pour la chaine comme ceci (dès que c'est possible)
La doc SDK de PB dit ceci (voir ci-dessous) mais là encore, rien de rien pour utiliser les macro Polink
VI. Managing strings
--------------------
Managing strings in PureBasic 4.0 and above isn't obvious anymore. If a function use strings but doesn't
returns string, there is not problem at all. Now when it returns string, there is different case:
1) The function doesn't has string parameter
It's the easiest one, and you can use the SYS_GetOutputBuffer() or SYS_GetOutputBufferESP() macro
in LCC.
SYS_GetOutputBuffer(char *Output, int NeededLength, char *NbParameters)
With this command you ask PureBasic to returns a string buffer of 'NeededLength' (in characters, which means
than it's the same value in unicode or not) and store the pointer value in 'Output'. 'NbParameters' is a
string number which indicates how many parameters the function has.
ex: SYS_GetOutputBuffer(Output, 100, "2")
Once you get this buffer, just write the string result in it and you're done.
Note: the 'NeededLength' should be the exact returned string length. It doesn't count the null terminating character
WARNING: When using LCC, there is sometimes an issue when the function doesn't have any parameters, and is very short.
LCC then optimize it by using only registers and then SYS_GetOutputBuffer() will fails. In this case, you can generate
the .asm code and check the procedure start, if ebp is used or not. If not, you will have to use SYS_GetOutputBufferESP()
and put the offset number. It very rare case, but can happen.
2) If the function has some string parameters
You still have to use the above functions, but before you may need to to call SYS_GetParameterIndex() and SYS_ResolveParameter()
if you need to use the string parameters after having called SYS_GetOutputBuffer(). Why that ? Because if one of your
parameter is a composed string (like a$+b$), it will reside on the internal buffer. When you request some length (let's say
a big length), it can be reallocated, which means than your string pointers won't be correct anymore. SYS_GetParameterIndex() will
get the index in the buffer, if the string is in the buffer (or return 0 else). SYS_ResolveParameter() will rebuild the
string pointer once SYS_GetOutputBuffer() will be called.
A typical C code will look like that:
M_PBFUNCTION void PB_LSet(const TCHAR *String, int Length)
{
[...]
ParameterIndex = SYS_GetParameterIndex(String);
SYS_GetOutputBuffer(Cursor, StringLength, "2");
if (ParameterIndex)
String = SYS_ResolveParameter(ParameterIndex);
[...]
}
Now, sometimes you can't know the size of the result string (or it will be too long to compute it. In this can, you
can request a fixed size and adjust it at the end with the SYS_ReduceStringSize(Length) function. 'Length' is the
number of byte to reduce the buffer. If you have requested a buffer of 4096 with SYS_GetOutputBuffer() and your
string do only 4000 bytes, you will have to reduce it from 96 bytes ie: SYS_ReduceStringSize(96).