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, y compris un résumé des attributs MIDL, consultez Définitions d’interface et bibliothèques de types dans le Guide et 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éreront des fichiers proxy/stub, ainsi que du code et des fichiers d’en-tête de marshaling. 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 d’importation IDL 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, dont IFace1 et IFace2 dérivent.
L’attribut object 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 du client RPC et du serveur. Les méthodes d’interface objet doivent avoir un type de retour HRESULT pour permettre au mécanisme RPC sous-jacent de signaler des erreurs pour les appels qui ne se terminent pas 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, d’IUnknown.
Le paramètre in directionnel spécifie un paramètre défini uniquement par l’appelant. Le paramètre out spécifie les données qui sont renvoyées à 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, ref ou 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 pour l’index du 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 savoir à l’avance combien de données seront 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 status. 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 d’IDispatch, une interface double prend en charge Automation, qui est ce que spécifie l’attribut oleautomation . IFace3 importe Oaidl.idl pour obtenir la définition d’IDispatch.
L’instruction library définit la bibliothèque de types ExampleLib, qui a ses propres attributs uuid, helpstring et version .
Dans la définition de la bibliothèque de types, la directive importlib intègre une bibliothèque de types compilée. Toutes les définitions de bibliothèque de types doivent intégrer la bibliothèque de types de base définie dans Stdole32.tlb.
Cette définition de bibliothèque de types montre 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 classe de composant entièrement nouvelle, 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 library. 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.