{"id":37653,"date":"2004-10-05T07:00:00","date_gmt":"2004-10-05T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2004\/10\/05\/the-macros-for-declaring-and-implementing-com-interfaces\/"},"modified":"2004-10-05T07:00:00","modified_gmt":"2004-10-05T07:00:00","slug":"the-macros-for-declaring-and-implementing-com-interfaces","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20041005-00\/?p=37653","title":{"rendered":"The macros for declaring and implementing COM interfaces"},"content":{"rendered":"<p><P>\nThere are two ways of declaring COM interfaces, the hard way\nand the easy way.\n<\/P>\n<P>\nThe easy way is to use an IDL file and let the MIDL compiler\ngenerate your COM interface for you.\nIf you let MIDL do the work, then you also get\n<A HREF=\"http:\/\/msdn.microsoft.com\/library\/en-us\/vccelng\/htm\/key_s-z_7.asp\">\n__uuidof<\/A> support at no extra charge, which is a very nice bonus.\n<\/P>\n<P>\nThe hard way is to do it all by hand.  If you choose this route,\nyour interface will look something like this:\n<\/P>\n<PRE>\n#undef  INTERFACE\n#define INTERFACE   ISample2<\/p>\n<p>DECLARE_INTERFACE_(ISample2, ISample)\n{\n    BEGIN_INTERFACE<\/p>\n<p>    \/\/ *** IUnknown methods ***\n    STDMETHOD(QueryInterface)(THIS_ REFIID riid, void **ppv) PURE;\n    STDMETHOD_(ULONG,AddRef)(THIS) PURE;\n    STDMETHOD_(ULONG,Release)(THIS) PURE;<\/p>\n<p>    \/\/ ** ISample methods ***\n    STDMETHOD(Method1)(THIS) PURE;\n    STDMETHOD_(int, Method2)(THIS) PURE;<\/p>\n<p>    \/\/ *** ISample2 methods ***\n    STDMETHOD(Method3)(THIS_ int iParameter) PURE;\n    STDMETHOD_(int, Method4)(THIS_ int iParameter) PURE;<\/p>\n<p>    END_INTERFACE\n};\n<\/PRE>\n<P>\nWhat are the rules?\n<\/P>\n<UL>\n<LI>You must set\nthe <CODE>INTERFACE<\/CODE> macro to the name of the interface being\ndeclared.\nNote that you need to <CODE>#undef<\/CODE> any previous value before you\n<CODE>#define<\/CODE> the new one.\n<LI>\nYou must use the <CODE>DECLARE_INTERFACE<\/CODE>\nand <CODE>DECLARE_INTERFACE_<\/CODE> macros\nto generate the preliminary bookkeeping for an interface.\nUse <CODE>DECLARE_INTERFACE<\/CODE> for interfaces that have no base class\nand <CODE>DECLARE_INTERFACE_<\/CODE> for interfaces that\nderive from some other interface.  In our example, we\nderive the <CODE>ISample2<\/CODE> interface from <CODE>ISample<\/CODE>.\n<STRONG>Note<\/STRONG>: In practice, you will never find\nthe plain <CODE>DECLARE_INTERFACE<\/CODE> macro because all interfaces\nderive from IUnknown if nothing else.\n<LI>\nYou must list all the methods of the base interfaces in exactly\nthe same order that they are listed by that base interface;\nthe methods that you are adding in the new interface must go last.\n<LI>\nYou must use the <CODE>STDMETHOD<\/CODE> or <CODE>STDMETHOD_<\/CODE>\nmacros to declare the\nmethods.  Use <CODE>STDMETHOD<\/CODE> if the return value is\n<CODE>HRESULT<\/CODE> and\n<CODE>STDMETHOD_<\/CODE> if the return value is some other type.\n<LI>\nIf your method has no parameters, then the argument list must\nbe <CODE>(THIS)<\/CODE>.\nOtherwise, you must insert <CODE>THIS_<\/CODE> immediately after\nthe open-parenthesis of the parameter list.\n<LI>\nAfter the parameter list and before the semicolon,\nyou must say <CODE>PURE<\/CODE>.\n<LI>\nInside the curly braces, you must say\n<CODE>BEGIN_INTERFACE<\/CODE> and\n<CODE>END_INTERFACE<\/CODE>.\n<\/UL>\n<P>\nThere is a reason for each of these rules.  They have to do with\nbeing able to use the same header for both C and C++ declarations\nand with interoperability with different compilers and platforms.\n<\/P>\n<UL>\n<LI>\nYou must set the <CODE>INTERFACE<\/CODE> macro because its value is used\nby the <CODE>THIS<\/CODE> and <CODE>THIS_<\/CODE> macros later.\n<LI>\nYou must use one of the <CODE>DECLARE_INTERFACE*<\/CODE> macros to ensure that\nthe correct prologue is emitted for both C and C++.\nFor C, a vtable structure is declared, whereas for C++\nthe compiler handles the vtable automatically; on the other hand,\nsince C++ has inheritance, the macros need to specify the base\nclass so that upcasting will work.\n<LI>\nYou must list the base class methods in exactly the same order\nas in the original declarations so that the C vtable structure\nfor your derived class matches the structure for the base class\nfor the extent that they overlap.  This is required to preserve\nthe COM rule that a derived interface can be used as a base\ninterface.\n<LI>\nYou must use the <CODE>STDMETHOD<\/CODE> and\n<CODE>STDMETHOD_<\/CODE> macros to ensure that\nthe correct calling conventions are declared for the function\nprototypes.\nFor C, the macro creates a function pointer in the vtable;\nfor C++, the macro creates a virtual function.\n<LI>\nThe <CODE>THIS<\/CODE> and <CODE>THIS_<\/CODE> macros\nare used so that the C declaration\nexplicitly declares the &#8220;this&#8221; parameter which in C++ is implied.\nDifferent versions are needed depending on the number of parameters\nso that a spurious trailing comma\nis not generated in the zero-parameter case.\n<LI>\nThe word <CODE>PURE<\/CODE> ensures that the C++ virtual function is pure,\nbecause one of the defining characteristics of COM interfaces\nis that all methods are pure virtual.\n<LI>\nThe <CODE>BEGIN_INTERFACE<\/CODE> and\n<CODE>END_INTERFACE<\/CODE> macros\nemit compiler-specific goo which the compiler vendor provides\nin order to ensure that the generated interface matches\n<A href=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2004\/02\/05\/68017.aspx\">\nthe COM vtable layout rules<\/A>.\nDifferent compilers have historically required different goo,\nthough the need for goo is gradually disappearing over time.\n<\/UL>\n<P>\nAnd you wonder why I called it &#8220;the hard way&#8221;.\n<\/P>\n<P>\nSimilar rules apply when you are implementing an interface.\nUse the <CODE>STDMETHODIMP<\/CODE> and\n<CODE>STDMETHODIMP_<\/CODE> macros to declare your\nimplementations so that they get the proper calling convention\nattached to them.\nWe&#8217;ll see examples of this\n<A HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2004\/10\/06\/238630.aspx\">\nnext time<\/A>.\n<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>There are two ways of declaring COM interfaces, the hard way and the easy way. The easy way is to use an IDL file and let the MIDL compiler generate your COM interface for you. If you let MIDL do the work, then you also get __uuidof support at no extra charge, which is a [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[2],"class_list":["post-37653","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-history"],"acf":[],"blog_post_summary":"<p>There are two ways of declaring COM interfaces, the hard way and the easy way. The easy way is to use an IDL file and let the MIDL compiler generate your COM interface for you. If you let MIDL do the work, then you also get __uuidof support at no extra charge, which is a [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/37653","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=37653"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/37653\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=37653"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=37653"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=37653"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}