IHTMLElementCollection_FIXED

Sujets variés concernant le développement en PureBasic
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

IHTMLElementCollection_FIXED

Message par nico »

Freak à corriger une interface pour qu'elle puisse fonctionner avec PureBasic.

J'aimerais bien comprendre les modifs apportés, varIndex\split[0] ne correspond pas à un variant alors pourquoi ça marche?

Code : Tout sélectionner

Structure VARIANT_SPLIT
  StructureUnion
    Variant.VARIANT
    Split.l[4]
  EndStructureUnion
EndStructure

Interface IHTMLElementCollection_FIXED
  QueryInterface(a,b)
  AddRef()
  Release()
  GetTypeInfoCount(a)
  GetTypeInfo(a,b,c)
  GetIDsOfNames(a,b,c,d,e)
  Invoke(a,b,c,d,e,f,g,h)
  toString(a)
  put_length(a)
  get_length(a)
  get__newEnum(a)
  item(a1,a2,a3,a4,b1,b2,b3,b4,c);(a,b,c)
  tags(a,b)
EndInterface 


varIndex.VARIANT_SPLIT\Variant\vt = #VT_I4
varIndex\Variant\lVal = 0

If *pElemColl\item(varIndex\split[0], varIndex\split[1], varIndex\split[2], varIndex\split[3], varIndex\split[0], varIndex\split[1], varIndex\split[2], varIndex\split[3], @*pElemDisp.IDispatch)=#S_OK
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Message par Anonyme2 »

Salut Nico,

tout est du au fait de la StructureUnion

Les éléments Variant et Split[0] partagent la même adresse (c'est au même emplacement en mémoire), la structure Variant réserve 16 octets et le tableau Split[4] également, le tout à la même adresse.

C'est le fond de ta question car je n'ai pas testé ton code :roll:

Code : Tout sélectionner

Structure VARIANT_SPLIT
  StructureUnion
    Variant.VARIANT
    Split.l[4]
  EndStructureUnion
EndStructure

Interface IHTMLElementCollection_FIXED
  QueryInterface(a,b)
  AddRef()
  Release()
  GetTypeInfoCount(a)
  GetTypeInfo(a,b,c)
  GetIDsOfNames(a,b,c,d,e)
  Invoke(a,b,c,d,e,f,g,h)
  toString(a)
  put_length(a)
  get_length(a)
  get__newEnum(a)
  item(a1,a2,a3,a4,b1,b2,b3,b4,c);(a,b,c)
  tags(a,b)
EndInterface


Var.VARIANT_SPLIT

Debug "@Var\Variant = " + Str(@Var\Variant)

Debug "@Var\Split[0] = " + Str(@Var\Split[0])


Debug OffsetOf(VARIANT_SPLIT\Variant)
Debug OffsetOf(VARIANT_SPLIT\Split)
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

Ok Denis, je commence à comprendre :lol:

Par contre, pourquoi le passage de valeurs passe avec le Split et pas le variant ?

Freak l'explique en disant ceci: mais qu'est ce que ça veut dire ?
(Directement sur la pile et pas comme une référence ?)
A few words:

To enumerate the objects (in whatever order), you always have to deal with the
IHTMLElementCollection interface, which represents a set of elements.
Well, here is a problem: The much needed IHTMLElementCollection::item() method
expects two VARIANT structures (which are 16 bytes) not as a reference, but
directly on the stack. The problem is that PB does not support that.
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Message par Anonyme2 »

Si on suit la doc MS (http://msdn2.microsoft.com/en-us/librar ... S.85).aspx),
la méthode item de l'interface IHTMLElementCollection accepte 3 paramètres dont les 2 premiers sont des variant.

Lors d'un appel de procedure avec des paramètres, chaque paramètre va être mis sur la pile (sa valeur et pas son adresse sauf si on précise que c'est l'adresse en utilisant un pointeur ou en utilisant le symbol @), le tout se faisant avec une valeur de type long (32 bits même si le paramètre est un octet). On voit tout suite la limite dans le cas de paramètres basés sur une structure; dans ce cas on passe sur la pile l'adresse et pas la valeur de l'élément. Le compilateur se débrouille pour accéder aux différents éléments avec l'adresse de base.

La méthode item de l'interface IHTMLElementCollection a besoin que l'on passe sur la pile les valeurs du variant, c'est à dire les 16 octets (4 mots de 32 bits), or en mode classique PB ne sait empiler qu'un mot de 32 bits par paramètre (et pour notre exemple il empilerait l'adresse).

En utilisant le prototype variant, le compilateur va comprendre qu'il faut empiler les valeurs du variant (4 mot de 32 bits) et pas l'adresse de la variable, sauf que ça ne devait pas aller correctement si Freak a modifié l'interface.

Code : Tout sélectionner

Interface IHTMLElementCollection
  QueryInterface(a, b)
  AddRef()
  Release()
  GetTypeInfoCount(a)
  GetTypeInfo(a, b, c)
  GetIDsOfNames(a, b, c, d, e)
  Invoke(a, b, c, d, e, f, g, h)
  toString(a)
  put_length(a)
  get_length(a)
  get__newEnum(a)
  item(a.p-variant, b.p-variant, c)
  tags(a.p-variant, b)
EndInterface
Dans ton exemple, l'interface est définie comme ceci :

Code : Tout sélectionner

Interface IHTMLElementCollection_FIXED
  QueryInterface(a,b)
  AddRef()
  Release()
  GetTypeInfoCount(a)
  GetTypeInfo(a,b,c)
  GetIDsOfNames(a,b,c,d,e)
  Invoke(a,b,c,d,e,f,g,h)
  toString(a)
  put_length(a)
  get_length(a)
  get__newEnum(a)
  item(a1,a2,a3,a4,b1,b2,b3,b4,c);(a,b,c)
  tags(a,b)
EndInterface 
Les éléments a1,a2,a3,a4,b1,b2,b3,b4 sont des mots de 32 bits, ce qui fait qu'en utilisant le tableau Split défini comme 4 éléments de 32 bits chacun, cela fonctionne. Si on tente d'utiliser à la place des éléments split, la variable Variant, on se retrouvera avec un problème de taille.

Si on utilise la variable variant, elle sera empilée par son adresse.
On pourrait avec un peu de bricolage empiler des PeekL(@Variant), PeekL(@Variant +4) etc, mais Freak a préféré l'usage d'un tabeau qui donne un meilleur code.

J'espère avoir été clair :roll:

A+
Denis
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

Merci Denis, c'est très clair; donc si j'ai un problème avec une interface qui demande un variant , il faudra que je vérifie si le paramètre demandé est un variant ou un pointeur vers un variant. :D
Répondre