Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

LES BIBLIOTHÈQUES DE TYPES (TYPELIB, TLB) ET LE LANGAGE ODL


Information sur le tutorial

Catégorie :Optimisation du code Date de création : 01/07/2005 12:29:57 Vu : 4 322 fois

Note :
Aucune note

Commentaire sur cette source (6)
Ajouter un commentaire et/ou une note


Description

Ce tutoriel est destiné à vous aider à créer des typelib pour vos interfaces et pour les interfaces que vous voulez utiliser. Cela servira aussi pour la définition des interfaces des objets légers...
Il traite aussi des aspects : constantes, structures et APIs qui sont déclarées dans une typelib afin de se passer de Declare...

Tutorial

1.    Un début de syntaxe

Une bibliothèque de types permet de décrire l’interface de l’objet quevous voulez créer. La description en langage ODL est compilée avec MkTypLib pour générer un fichier TLB. Ce fichier est à inclure dans les références du projet VB.


a.     La syntaxe d’unfichier ODL

Un fichier ODL a lasyntaxe suivante :

[

     uuid(<GUID>),

     version(<version>)

]

library <Nom de la bibliothèque>

{

     importlib("stdole2.tlb");

     [

          uuid(<GUID>),

          odl

     ]

     interface <Nom del’interface> : stdole.IUnknown {

          [<attributs>]<valeur de retour> <nomméthode>(<paramètres>);

     }

}

Tout ce qui se trouveentre crochets constitue les attributs de l’entité qui suit.

Le premier <GUID>doit être un GUID unique généré avec Guidgen. La version est dela forme Major.Minor.

Le second <GUID>(celui de l’interface) doit correspondre au GUID de l’interface, si vousimplémenté une interface existante ou un nouveau GUID si votre interfacen’existe pas.

Idéalement le nom del’interface commence par un I. Viennent ensuite, la liste des méthodes quidéfinit l’ordre dans la vtable.

<attributs> peut comprendre helpstring, vararg,propput, propputref, propget. La valeur de retour peutêtre soit HRESULT, soit n’importe quel type sauf un pointeur et il est préférableque ce ne soit pas une structure.Le nom de la méthode doit être unique dans l’interface (sauf pour les propput,propputrefet propget).

<paramètre>à la syntaxe suivante : [<marshaling>]<type dedonnée> <nom de paramètre>.

<marshaling>peut être soit [in], soit [in,out], soit [out,retval] et peut inclure defaultvalue(<valeur>).


b.     Intégrer unedescription du contenu

Pour fournir uneaide dans l’Explorateurd’objet de VB, vous pouvezrajouter entre n’importe quel [] l’attribut helpstring(« Description »)sauf dans les paramètres.

 

2.    Les Alias

Bien que VB ne puissepas définir d’alias, il sait très bien les utiliser sauf pour les Enums. Par exemple, on peut définir un alias delong (ou même unsigned long, VB ne le gère pas directement mais peut le gérer àtravers un alias. Pour les opérations, ils sont traités comme des signés). Unalias se définit dans un fichier ODL par :

     Typedef [public] <typede base> <nom de l’alias>

 

3.    Les constantes

Les constantes sedéfinissent obligatoirement dans un module. Les constantes se déclarent comme suit :

[

     dllname(« n’importequoi »)

]

module <nom du module>

{

     const <type> <nomconstante> = <valeur> ;

}

« n’importe quoi » c’est une chaîne quelconque puisque l’attribut dllname est obligatoire pour un module.

<type>et <valeur> ne peuvent être que des type simples : unsigned char, short, long, float (Single enVB), double, LPWSTR, LPSTR, BSTR et c’est tout…

Les chaînes sontdéfinies comme en C : on peut inclure les séquences d’échappement tellesque \n (nouvelle ligne), \t (tabulation), \r (retourà la ligne), \\ (\)…

 

4.    Les types de données de stdole pour VB

Nom en ODL

Nom en VB

Taille en octets

unsigned char

Byte

1

Short

Integer

2

Long

Long

4

Float

Single

4

Double

Double

8

currency

Currency

8

DATE

Date

8

BSTR

String

4 + 2 * nombre de caractères + 2

IDispatch*

Object

4

boolean

Boolean

2

VARIANT

Variant

16 au moins

SAFEARRAY(<type>)*

Tableau en paramètres

4

Struct

Type/End Type

Somme de la taille des members

SAFEARRAY(<type>)

Tableau de taille variable

24

<type> <nom>[<taille>]

Tableau fixe

Sizeof(<type>) * <taille>

Enum

Enum

4

LPSTR

Pas d’équivalent

Nombre de caractères + 1 (ANSI)

LPWSTR

Pas d’équivalent

2 * Nombre de caractères + 2 (UNICODE)

 

5.    Les structures

Dans le langage ODL,une structure se définit comme suit :

typedef struct {

     <type> <nom> ;

    

} <nom structure> ;

Dans une structure,on ne peut inclure que les types suivants :

·Les types simples : long, float, DATE,…

·Les types plus complexes :

o    Les tableaux : SAFEARRAY(<type>)

o    Les Variant : VARIANT

o    Les chaines : BSTR mais pas LPSTR, LPWSTR

o    Les tableaux de taille fixe : <type> <nom>[<taille>]

o    Les objets : <interface>*

A noter que l’on ne peut pas définir un typedef structqui porte le nom de GUID etsurement d’autres.

A noter aussi que l’on peut régler l’alignement des donnéesafin d’obtenir un alignement différents du 4 octets de VB. Sous mktyplib, cela se fait sur laligne de commande /align <valeur>.

 

6.    Les modules : une autre façon de déclarer des APIs

Un module permet aussi de déclarer des fonctions de DLLs.

La syntaxe est la suivante :

[

     dllname(« <nom de ladll> »)

]

module <Nomdu module>

{

     [entry(<index ou nom>)]<type> <nom de fonction>(<paramètres>) ;

    

}

<index ou nom> est soit le nom dela fonction, soit sont index. <nom de la dll>est le nom de la dll (avec ou sans chemin).

A noter, une restriction dans les attributs desparamètres : on ne peut pas utiliser retval. Nous sommes donclimité à [in] et [in,out].


7.    Ce que VB ne sait pas gérer dans les typelibs

Tout ce qui va êtredéfinit ici doit être remplacépour être utilisé par VB :

·       Les paramètres« tableau par valeur ».VB ne sait gérer que les tableaux passés par référence(SAFEARRAY(<type>)* en ODL).

·       Les paramètres« structures par valeur ».VB ne sait gérer les structures passés par référence (<structure>*en ODL). Il faut déclarer autant de paramètre de type Long que de champsdans la structure et ainsi remplir la pile avec les champs de la structure

·       Les pointeursdans les structures. Il suffit deles remplacer par des long.

·       Les types nonsignés. VB ne gère comme type nonsigné que Byte qui est un unsigned char. VB ne sait gérerni char (ne pas confondre avec char*) ni int. Il suffit deremplacer tous les unsigned long ou short par longet short et, char par unsigned char.

·       Les chaines decaractères de taille fixe dans une structure. Il faut le remplacer par un tableau de short <nom>[<taille>].

·       Les unions.

·       Les paramètresde type [out] <type>*.Il peut être remplacé par [in,out]<type>* si l’on passe toujoursune variable ou par [in] long si l’on est amené à passer un NULL(0). On peut enfin le transformer en [out,retval] si c’est le dernierparamètre. Il ne peut y avoir qu’un seul [out,retval]. Il devientalors la valeur de retour de la fonction. Voir plus loin pour les valeurs de retour.

 

8.    VB-izé une interface

Pour trouver uneinterface déjà définie, vous pouvez utiliser l’utilitaire OleView.exeet récupérer son IID (GUID).

  • Vérifié que vous N’avez PAS les attributs oleautomation et dual dans les attributs des interfaces. Ajoutez l’attribut odl.
  • Ajouter en tête toutes les fonctions des interfaces dont l’interface hérite sauf IUnknown. L’interface doit dériver de IUnknown. Sa déclaration doit être : interface <nom de l’interface> : stdole.IUnknown.
  • Remplacer tout ce que VB ne supporte pas  par les équivalents (voir section « Ce que VB ne sait pas gérer dans les typelibs »)
  • Changer tout ce qu’il faut pour que VB arrête de faire le difficile

 

9.    Les différents type de paramètres pour les fonctions

Tous les types debases : Byte, Integer, Long, Single, Double, Boolean, Currency, Date, Enum sont des types qui peuvent être passédirectement par valeur. Pour ces types, si le paramètre estdéfini :

·       [in] <type> , c’estun ByVal As <type>

·       [in,out] <type>*, c’est un ByRef As <type>

<type>est à choisir parmi un nom d’enum, unsigned char, short,long, float, double, boolean, currency, DATE.

Il n’y pas d’autrescombinaisons. A noter que pour ces types, on peut définir une valeur pardéfaut, qui rend le paramètre optionnel, avec l’attribut defaultvalue(<valeur>).

Les types String (BSTR, LPSTR, LPWSTR), Object (IDispatch*)et autres types objets (toutes les interfaces) sont, par définition,des types pointeurs. Pour ces types, on définit :

  • [in] BSTR, [in] LPSTR, [in] LPWSTR, c’est un ByVal As String
  • [in,out] BSTR*, [in,out] LPSTR*, [in,out] LPWSTR*, c’est un ByRef As String
  • [in] IDispatch*, c’est un ByVal As Object
  • [in,out] IDispatch**, c’est un ByRef As Object

A noter que ByRef As Object (ou As <interface>) n’est nécessaire que lorsque l’on compte modifier la référenced’objet, ou en renvoyer une. Pour un simple passage de paramètre à des finsd’utilisation, on optera toujours pour un ByVal

Les types tableauxsont eux aussi des pointeurs :

  • [in] SAFEARRAY(<type>)* et [in,out] SAFEARRAY(<type>)* sont équivalent puisque l’on ne peut pas passer de tableau par valeur.

<type>est n’importe quel type, simple, structure ou tableau.

 

10. Lesparamètres [out,retval]

Le dernier paramètre de la liste peut être attribué avec [out,retval]s’il est du type ByRef c’est à dire pointeur (long*, boolean*,…, BSTR*, IDispatch**, <interface>**, …). Il nepeut y en avoir qu’un seul.

 

11. LesParamArray : l’attribut vararg

Pour déclarer que la liste des paramètres n’est pas connue àpartir d’un certain paramètre, on utilise ParamArray suivi d’unnom de paramètre de type tableau de Variant (sous VB). En langageODL, il faut ajouter vararg dans les attributs de la méthode(et non dans les attributs du paramètre). Il s’en suit une définition deméthode comme suit :

[vararg] <type><nom>(<liste de paramètres connus>,SAFEARRAY(VARIANT)*<nom arg>) ;

 

12. Lespropriétés : les attributs propput, propputref et propget

Pour déclarer une propriété en lecture-écriture, ilfaut deux fonctions : une pour lire et une pour écrire.Nous distinguerons deux cas :

·       Les propriétés pour types normaux

·       Les propriétés pour types objets

 

  1. Les propriétés normales : Property Get / Property Let (propget / propput)

Une propriété de ce type aura deux entrées dans la vtable.En langage ODL, elle auront le prototype suivant :

  • Pour la lecture, Property Get :
    • [propget] HRESULT <nom propriété>([out,retval] <type>* <nom>) ;
  • Pour l’écriture, Property Let :
    • [propput] HRESULT <nom propriété>([in] <type> <nom>);

 

  1. Les propriétés objets : Property Get / Property Set (propget /propputref)

Une propriété de ce type aura deux entrées dans la vtable.En langage ODL, elle auront le prototype suivant :

  • Pour la lecture, Property Get :
    • [propget] HRESULT <nom propriété>([out,retval] <interface>** <nom>) ;
  • Pour l’écriture, Property Let :
    • [propputref] HRESULT <nom propriété>([in] <interface>* <nom>);

On peut aussi avoir des propriétés en lecture-seule ouécriture-seule en supprimant une des deux fonctions.

 

Exemples de fichier ODL (extrait, voir source surles propriétés NTFS, Office…) :

[

   uuid(b7e2416d-ea73-43f1-a7c6-b47e9a7f3fac),

   helpstring("IPropertySet"),

   version(1.0)

]

library Properties

{

   importlib("stdole2.tlb");

//déclaration forward

   interfaceIStream;

   interfaceIstorage;

   interfaceIEnumSTATSTG;

//Types et enums

typedef [helpstring("Moded'accès")] enum STGM {

      [helpstring("Direct")]

    STGM_DIRECT = 0x00000000,

      [helpstring("AvecAnnulation possible (Transaction)")]

    STGM_TRANSACTED = 0x00010000,

      [helpstring("Simple")]

    STGM_SIMPLE = 0x08000000,

      [helpstring("Accèsen lecture")]

    STGM_READ = 0x00000000,

      [helpstring("Accèsen écriture")]

    STGM_WRITE = 0x00000001,

      [helpstring("Accèsen lecture-écriture")]

    STGM_READWRITE = 0x00000002,

} STGM;

//alias privé

typedef unsigned char BYTE;

//type

typedef [helpstring("Entier64bits")] struct tagULARGE {

      LONG lowDWORD;

      LONG highDWORD;

} ULARGE;

typedef [helpstring("UniversalUnique IDentifier")] struct tagUUID {

    LONG Data1;

    SHORT Data2;

    SHORT Data3;

    BYTE Data4[8];

} UUID;

typedef [helpstring("Structurede statistiques sur l'objet de stockage")] structtagSTATSTG {

      [helpstring("Nom")]

    LONG pwcsName;

      [helpstring("Type")]

    STGTY type;

      [helpstring("Taille")]

    LONG cbSizeLow;

      [helpstring("Taille")]

    LONG cbSizeHigh;

      [helpstring("Datede dernière modification")]

    FILETIME mtime;

      [helpstring("Date decréation")]

    FILETIME ctime;

      [helpstring("Date dudernier accès")]

    FILETIME atime;

      [helpstring("Moded'accès")]

    STGM grfMode;

      [helpstring("Type de vérouillagesupporté")]

    LOCKTYPE grfLocksSupported;

      [helpstring("CLSID")]

    UUID clsid;

      [helpstring("Etat")]

    LONG grfStateBits;

    LONG reserved;

} STATSTG;

 

// IEnumSTATSTG

[

    odl,

    uuid(0000000d-0000-0000-C000-000000000046),

      helpstring("Enumère lesinformations statistiques")

]

interface IEnumSTATSTG :stdole.IUnknown {

      [helpstring("Renvoiele statistique suivante")]

    LONG Next(

        [in]LONG celt,

        [out]STATSTG *rgelt,

        [out,defaultvalue(0)] LONG *pceltFetched);

      [helpstring("Passela statistique actuelle")]

    HRESULT Skip(

        [in]LONG celt);

      [helpstring("Réinitialise")]

    HRESULT Reset();

      [helpstring("Dupliquel'interface")]

    HRESULT Clone(

        [out,retval] IEnumSTATSTG **ppenum);

}

 

//IStorage

 

    [

        odl,

        uuid(0000000b-0000-0000-C000-000000000046),

        helpstring("Permet decréer et de gérer les objets de stockage structuré")

    ]

    interfaceIStorage : stdole.IUnknown {

            [helpstring("Crée un flux de stockage")]

        HRESULT CreateStream(

            [in] LPWSTR pwcsName,

            [in] STGM grfMode,

            [in, defaultvalue(0)]LONG reserved1,

            [in, defaultvalue(0)]LONG reserved2,

            [out, retval] IStream**ppstm);

            [helpstring("Ouvre un flux de stockage")]

        HRESULT OpenStream(

            [in] LPWSTR pwcsName,

            [in] LONG reserved1,

            [in] STGM grfMode,

            [in, defaultvalue(0)]LONG reserved2,

            [out, retval] IStream**ppstm);

            [helpstring("Crée unstockage")]

        HRESULT CreateStorage(

            [in] LPWSTR pwcsName,

            [in] STGM grfMode,

            [in, defaultvalue(0)]LONG reserved1,

            [in, defaultvalue(0)]LONG reserved2,

            [out, retval] IStorage**ppstg);

            [helpstring("Ouvre unstockage")]

        HRESULT OpenStorage(

            [in] LPWSTR pwcsName,

            [in] LONG pstgPriority,

            [in] STGM grfMode,

            [in, defaultvalue(0)]LONG snbExclude,

            [in, defaultvalue(0)]LONG reserved,

            [out, retval] IStorage**ppstg);

            [helpstring("Copie le contenu de ce stockage dansun autre")]

        HRESULT CopyTo(

            [in] LONG ciidExclude,

            [in] void*rgiidExclude,

            [in] LPWSTR snbExclude,

            [in]IStorage *pstgDest);

            [helpstring("Déplace le contenu de ce stockagedans un autre")]

        HRESULT MoveElementTo(

            [in] LPWSTR pwcsName,

            [in] IStorage*pstgDest,

            [in] LPWSTR*pwcsNewName,

            [in] STGMOVE grfFlags);

            [helpstring("Enregistre le stockage")]

        HRESULT Commit(

            [in, defaultvalue(0)] STGC grfCommitFlags);

            [helpstring("Annule les actions précedant àl'appel de cette méthode")]

        HRESULT Revert();

            [helpstring("Enumère les stockages et flux de cestockage")]

        HRESULT EnumElements(

            [in, defaultvalue(0)]LONG reserved1,

            [in, defaultvalue(0)]LONG reserved2,

            [in, defaultvalue(0)]LONG reserved3,

            [out, retval]IEnumSTATSTG **ppenum);

            [helpstring("Supprime un stockage ou flux de cestockage")]

        HRESULT DestroyElement(

            [in] LPWSTR pwcsName);

            [helpstring("Renomme un stockage ou un flux de cestockage")]

        HRESULT RenameElement(

            [in] LPWSTRpwcsOldName,

            [in] LPWSTRpwcsNewName);

            [helpstring("Enregistre les dates d'accès")]

        HRESULT SetElementTimes(

            [in] LPWSTR pwcsName,

            [in] FILETIME *pctime,

            [in] FILETIME *patime,

            [in] FILETIME *pmtime);

            [helpstring("Définit la classe destockage")]

        HRESULT SetClass(

            [in] UUID *clsid);

            [helpstring("Définit l'état du stockage")]

        HRESULT SetStateBits(

            [in] LONG grfStateBits,

            [in] LONG grfMask);

            [helpstring("Obtient des statistiques sur cestockage")]

        HRESULT Stat(

            [in,out] STATSTG*pstatstg,

            [in, defaultvalue(0)] STATFLAG grfStatFlag);

    }
}

signaler à un administrateur
Commentaire de ShareVB le 05/07/2005 11:48:03

Je cite ma source, tout en disant que ce n'est pas du copier coller, ni du texte, ni du code :

Advanced Visual Basic 6
Power Techniques for Everyday Programs
Matthew Curland
www.powervb.com

Si vous voulez encore plus d'infos sur VB, achetez et lisez ce livre...

ShareVB

signaler à un administrateur
Commentaire de Gobillot le 06/07/2005 19:48:43

1) pourquoi on n'a pas accès au tutorial 173 ?

2) pour LPSTR d'accord il n'y a pas d'équivallent en interne,
   cependant Vb est capable de transformer une BSTR en LPSTR
   c'est ce qu'il fait quand il passe une chaine
   à une fonction externe.

signaler à un administrateur
Commentaire de ShareVB le 07/07/2005 10:28:23

salut,

1)je n'avais pas remarquer : je vais demander aux admins...

2)de toute façon, LPSTR, LPWSTR et BSTR sont tous équivalents de String pour VB depuis une typelib..."en affichage" du moins.

ShareVB

signaler à un administrateur
Commentaire de Afyn le 13/07/2005 14:35:33

Sinon tu peux reposter le 173 ?

Afyn - Navedac

signaler à un administrateur
Commentaire de ShareVB le 14/07/2005 10:43:12

salut,

visiblement, merci aux admins d'avoir corrigé le bug du tuto 173...

ShareVB

signaler à un administrateur
Commentaire de ShareVB le 11/08/2006 21:49:34

salut à tous,

retrouvez ce tuto sur mon site perso à www.sharevb.net...rubrique Programmation\VB\

ShareVB

Ajouter un commentaire



Nos sponsors

Sondage...

CalendriCode

Octobre 2008
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel BAÏSE, Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,031 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.