Anatomie d’un fichier IDL
Ces exemples de fichiers IDL illustrent les constructions fondamentales de la définition d’interface. L’allocation de mémoire, le marshaling personnalisé et la messagerie asynchrone ne sont que quelques-unes des fonctionnalités que vous pouvez implémenter dans une interface COM personnalisée. Les attributs MIDL sont utilisés pour définir des interfaces COM. Pour plus d’informations sur l’implémentation d’interfaces et de bibliothèques de types, notamment un résumé des attributs MIDL, consultez Définitions d’interface et bibliothèques de types dans le Guide et la référence du programmeur MIDL. Pour obtenir une référence complète de tous les attributs, mots clés et directives MIDL, consultez la référence du langage MIDL.
Example.idl
L’exemple de fichier IDL suivant définit deux interfaces COM. À partir de ce fichier IDL, Midl.exe générera des fichiers proxy/stub et marshaling du code et des fichiers d’en-tête. Une dissection ligne par ligne suit l’exemple.
//
// Example.idl
//
import "mydefs.h","unknwn.idl";
[
object,
uuid(a03d1420-b1ec-11d0-8c3a-00c04fc31d2f),
] interface IFace1 : IUnknown
{
HRESULT MethodA([in] short Bread, [out] BKFST * pBToast);
HRESULT MethodB([in, out] BKFST * pBPoptart);
};
[
object,
uuid(a03d1421-b1ec-11d0-8c3a-00c04fc31d2f),
pointer_default(unique)
] interface IFace2 : IUnknown
{
HRESULT MethodC([in] long Max,
[in, max_is(Max)] BkfstStuff[ ],
[out] long * pSize,
[out, size_is( , *pSize)] BKFST ** ppBKFST);
};
L’instruction IDL importer est utilisée ici pour importer un fichier d’en-tête, Mydefs.h, qui contient des types définis par l’utilisateur et Unknwn.idl, qui contient la définition de IUnknown , à partir duquel IFace1 et IFace2 dérivent.
L’objet attribut identifie l’interface en tant qu’interface objet et indique au compilateur MIDL de générer du code proxy/stub au lieu des stubs client et serveur RPC. Les méthodes d’interface objet doivent avoir un type de retour de HRESULT, pour permettre au mécanisme RPC sous-jacent de signaler les erreurs d’appels qui échouent en raison de problèmes réseau.
L’attribut uuid spécifie l’identificateur d’interface (IID). Chaque interface, classe et bibliothèque de types doit être identifiée avec son propre identificateur unique. Utilisez l’utilitaire Uuidgen.exe pour générer un ensemble d’ID uniques pour vos interfaces et d’autres composants.
L’interface mot clé définit le nom de l’interface. Toutes les interfaces d’objet doivent dériver, directement ou indirectement, de IUnknown .
Le dans paramètre directionnel spécifie un paramètre défini uniquement par l’appelant. Le paramètre spécifie les données transmises à l’appelant. L’utilisation des deux attributs directionnels sur un paramètre spécifie que le paramètre est utilisé à la fois pour envoyer des données à la méthode et pour transmettre des données à l’appelant.
L’attribut pointer_default spécifie le type de pointeur par défaut (unique, refou ptr) pour tous les pointeurs, à l’exception de ceux inclus dans les listes de paramètres. Si aucun type par défaut n’est spécifié, MIDL suppose que les pointeurs uniques sont uniques . Toutefois, lorsque vous avez plusieurs niveaux de pointeurs, vous devez spécifier explicitement un type de pointeur par défaut, même si vous souhaitez que le type par défaut soit unique.
Dans l’exemple précédent, le tableau BkfstStuff[ ] est un tableau conforme, dont la taille est déterminée au moment de l’exécution. L’attribut max_is spécifie la variable qui contient la valeur maximale de l’index de tableau.
L’attribut size_is est également utilisé pour spécifier la taille d’un tableau ou, comme dans l’exemple précédent, plusieurs niveaux de pointeurs. Dans l’exemple, l’appel peut être effectué sans connaître à l’avance la quantité de données retournées.
Example2.idl
L’exemple IDL suivant (qui réutilise les interfaces décrites dans l’exemple IDL précédent) montre les différentes façons de générer des informations de bibliothèque de types pour les interfaces.
//
// Example2.idl
//
import "example.idl","oaidl.idl";
[
uuid(a03d1422-b1ec-11d0-8c3a-00c04fc31d2f),
helpstring("IFace3 interface"),
pointer_default(unique);
dual,
oleautomation
]
interface IFace3 : IDispatch
{
HRESULT MethodD([in] BSTR OrderIn,
[out, retval] * pTakeOut);
}; //end IFace3 def
[
uuid(a03d1423-b1ec-11d0-8c3a-00c04fc31d2f),
version(1.0),
helpstring("Example Type Library"),
] library ExampleLib
{
importlib("stdole32.tlb");
interface IFace3;
[
uuid(a03d1424-b1ec-11d0-8c3a-00c04fc31d2f),
helpstring("Breakfast Component Class")
] coclass BkfstComponent
{
[default]interface IFace1;
interfaceIFace2
}; //end coclass def
[
uuid(a03d1424-b1ec-11d0-8c3a-00c04fc31d2f),
helpstring("IFace4 interface"),
pointer_default(unique);
dual,
oleautomation
]
interface IFace4 : IDispatch
{
[propput] HRESULT MethodD([in] BSTR OrderIn);
[propget] HRESULT MethodE([out, retval] * pTakeOut);
}; //end IFace4 def
}; //end library def
L’attribut helpstring est facultatif ; vous l’utilisez pour décrire brièvement l’objet ou pour fournir une ligne d’état. Ces chaînes d’aide sont lisibles avec un navigateur d’objets tel que celui fourni avec Microsoft Visual Basic.
L’attribut double sur IFace3 crée une interface qui est à la fois une interface de répartition et une interface COM. Étant donné qu’elle est dérivée de IDispatch, une interface double prend en charge Automation, c’est-à-dire ce que spécifie l’attribut oleautomation. IFace3 importe Oaidl.idl pour obtenir la définition de IDispatch.
L’instructionbibliothèque dedéfinit la bibliothèque de types ExampleLib, qui a ses propres uuid, helpstringet les attributs version.
Dans la définition de bibliothèque de types, la directive importlib apporte une bibliothèque de types compilée. Toutes les définitions de bibliothèque de types doivent introduire la bibliothèque de types de base définie dans Stdole32.tlb.
Cette définition de bibliothèque de types illustre trois façons différentes d’inclure des interfaces dans la bibliothèque de types. IFace3 est inclus simplement en le référençant dans l’instruction de bibliothèque.
L’instruction coclasse définit une nouvelle classe de composant, BkfstComponent, qui inclut deux interfaces précédemment définies, IFace1 et IFace2. L’attribut par défaut désigne IFace1 comme interface par défaut.
IFace4 est décrit dans l’instruction de bibliothèque. L’attribut propput sur MethodD indique que la méthode effectue une action set sur une propriété du même nom. L’attribut propget indique que la méthode récupère des informations à partir d’une propriété du même nom que la méthode. L’attribut retval dans MethodD désigne un paramètre de sortie qui contient la valeur de retour de la fonction.