<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx</link><description>The Win32 COM calling convention specifies the layout of
the virtual method table (vtable) of an object.
If a language/compiler wants to support COM, it must lay
out its object in the specified manner so other components
can use it. It is no coincidence</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>re: The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#68044</link><pubDate>Thu, 05 Feb 2004 15:30:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:68044</guid><dc:creator>Ian Hanschen</dc:creator><description>Raymond,&lt;br&gt;Good read.&lt;br&gt;&lt;br&gt;How are you creating your diagrams?  Manually writing the HTML, using Word, or?  I really dislike having to use photoshop to throw something together that's going to sit in html that would look just fine using vml/tables.&lt;br&gt;-Ian</description></item><item><title>You know COM is dead when...</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#68056</link><pubDate>Thu, 05 Feb 2004 18:49:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:68056</guid><dc:creator>Paul's Imaginary Friend</dc:creator><description /></item><item><title>Raymond Chen on the layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#68216</link><pubDate>Thu, 05 Feb 2004 23:39:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:68216</guid><dc:creator>BufferOverrun</dc:creator><description /></item><item><title>re: The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#68433</link><pubDate>Fri, 06 Feb 2004 04:21:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:68433</guid><dc:creator>Norman Diamond</dc:creator><description>For a change of pace I have a genuine technical question as a followup, and it even reveals some of my incompetence.&lt;br&gt;&lt;br&gt;When a COM object is designed with a dual interface, access to the COM interface is pretty straightforward, callable from Visual Basic and JavaScript etc.  The COM interface is also more or less accessible by C++ applications, depending on what fraction of the DLL's Type Library is understood by Class Wizard.  For example if the COM interface uses SAFEARRAYs and the .odl file imports &amp;quot;oaidl.idl&amp;quot; (which by the way is a different file than MSDN says to import for SAFEARRAY) then Visual Basic arrays map onto it perfectly but VC++ clients don't get interfaces generated by Class Wizard.&lt;br&gt;&lt;br&gt;However, the purpose of a dual interface is that the VTBL interface should also be visible to VC++ clients, right?  Then the DLL can export methods using unsafe arrays and VC++ clients can call those methods directly, right?&lt;br&gt;&lt;br&gt;But I've never figured out how to code a VC++ application to access the VTBL interface of classes/methods exported from a DLL.  If I try to #include the relevant .h files of the DLL itself then those bring in all kinds of baggage related to the fact that the DLL is a COM server.  If I use Class Wizard to generate a .h file from the Type Library then we're back to the COM interface (and the limitations of Class Wizard).  I think I have sufficient skills to hand-code a .h file that will result in compiling the client application, but I'm very suspicious of doing things this way.  The purpose of a dual interface is to expose both interfaces to clients, VC++ wizards generate all sorts of code to assist developers, and I don't think tedious hand-construction of one .h file fits this scenario.  There must be something I'm missing.</description></item><item><title>re: The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#68475</link><pubDate>Fri, 06 Feb 2004 06:02:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:68475</guid><dc:creator>Ian Hanschen</dc:creator><description>Perhaps I'm misunderstanding your question but why not use the #import directive?&lt;br&gt;&lt;a target="_new" href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_predir_the_.23.import_directive.asp"&gt;http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_predir_the_.23.import_directive.asp&lt;/a&gt;&lt;br&gt;-Ian</description></item><item><title>re: The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#68512</link><pubDate>Fri, 06 Feb 2004 07:20:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:68512</guid><dc:creator>Norman Diamond</dc:creator><description>2/5/2004 10:02 PM Ian Hanschen:&lt;br&gt;&lt;br&gt;&amp;gt; why not use the #import directive?&lt;br&gt;&lt;br&gt;Isn't the effect the same?  It interprets the DLL's Type Library and produces new classes which mostly describe the COM object's COM interface?&lt;br&gt;&lt;br&gt;I want to try accessing the COM object's VTBL interface but can't figure out how.  I thought the purpose of a dual interface was that clients could access it either way, not being restricted to COM interface (in the case of C++, not being restricted to the portion of the COM interface that VC++ tools understand).</description></item><item><title>re: The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#68585</link><pubDate>Fri, 06 Feb 2004 10:53:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:68585</guid><dc:creator>Mike Dimmick</dc:creator><description>Norman:&lt;br&gt;&lt;br&gt;A dual interface has the same structure whether you access it through the vtable or through IDispatch. The methods have the same types. If you want a more C++-friendly interface, use a custom interface.&lt;br&gt;&lt;br&gt;The #import statement produces vtable access code; ClassWizard always produces IDispatch access code.</description></item><item><title>re: The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#68591</link><pubDate>Fri, 06 Feb 2004 11:07:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:68591</guid><dc:creator>Nate</dc:creator><description>Internet Explorer, it still can't render transparent PNGs properly, but it can display VML.....</description></item><item><title>re: The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#68594</link><pubDate>Fri, 06 Feb 2004 11:10:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:68594</guid><dc:creator>Reuben Harris</dc:creator><description>I thought the purpose of a dual interface was to allow clients to invoke methods either natively or by name (through IDispatch). Both involve calling through interface pointers...&lt;br&gt;&lt;br&gt;Were you hoping for a plain C++ class with normal methods corresponding to what's the typelib?</description></item><item><title>re: The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#68656</link><pubDate>Fri, 06 Feb 2004 14:07:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:68656</guid><dc:creator>Raymond Chen</dc:creator><description>Reuben is correct. The point of dual interfaces is that instead of&lt;br&gt;&lt;br&gt;IDispatch *pd;&lt;br&gt;CoCreateInstance(CLSID_Shell, NULL, CLSCTX_ALL, IID_IDispatch, &amp;amp;pd);&lt;br&gt;LPOLESTR pszCmd = L&amp;quot;ControlPanelItem&amp;quot;;&lt;br&gt;DISPID dispid;&lt;br&gt;pd-&amp;gt;GetIDsOfNames(IID_NULL, &amp;amp;pszCmd, 1, LOCAL_SYSTEM_DEFAULT, &amp;amp;dispid);&lt;br&gt;VARIANT vt;&lt;br&gt;V_VT(&amp;amp;vt) = VT_BSTR;&lt;br&gt;V_BSTR(&amp;amp;vt) = SysAllocString(L&amp;quot;keyboard&amp;quot;);&lt;br&gt;DISPPARAMS dp = { &amp;amp;vt, NULL, 1, 0 };&lt;br&gt;pd-&amp;gt;Invoke(dispid, IID_NULL, LOCAL_SYSTEM_DEFAULT, DISPATCH_METHOD, &amp;amp;dp, NULL, NULL, NULL);&lt;br&gt;&lt;br&gt;you can do this:&lt;br&gt;&lt;br&gt;#include &amp;lt;shldisp.h&amp;gt;&lt;br&gt;IShellDispatch *psd;&lt;br&gt;CoCreateInstance(CLSID_Shell, NULL, CLSCTX_ALL, IID_IShellDispatch, &amp;amp;psd);&lt;br&gt;BSTR bs = SysAllocString(L&amp;quot;keyboard&amp;quot;);&lt;br&gt;psd-&amp;gt;ControlPanelItem(bs);</description></item><item><title>re: The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#68701</link><pubDate>Fri, 06 Feb 2004 15:11:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:68701</guid><dc:creator>Paul Bartlett</dc:creator><description>I also think that Norman thought dual interfaces would allow certain parameter types to be treated differently (he mentions SAFEARRAY and &amp;quot;unsafe&amp;quot; arrays, which I take to mean conformant, or counted, arrays as the size is needed by the marshalling code). Unfortunately this is not the case. Dual interfaces merely permit &amp;quot;normal&amp;quot; or IDispatch-based calling (a.k.a. early and late binding)</description></item><item><title>Adjustor thunks</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#69674</link><pubDate>Sun, 08 Feb 2004 20:09:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:69674</guid><dc:creator>The Old New Thing</dc:creator><description /></item><item><title>re: The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#69842</link><pubDate>Mon, 09 Feb 2004 03:45:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:69842</guid><dc:creator>Norman Diamond</dc:creator><description>2/6/2004 6:07 AM Raymond Chen:&lt;br&gt;&lt;br&gt;&amp;gt; #include &amp;lt;shldisp.h&amp;gt;&lt;br&gt;&amp;gt; IShellDispatch *psd;&lt;br&gt;&amp;gt; CoCreateInstance(CLSID_Shell, NULL,&lt;br&gt;&amp;gt;    CLSCTX_ALL, IID_IShellDispatch, &amp;amp;psd);&lt;br&gt;&amp;gt; BSTR bs = SysAllocString(L&amp;quot;keyboard&amp;quot;);&lt;br&gt;&amp;gt; psd-&amp;gt;ControlPanelItem(bs);&lt;br&gt;&lt;br&gt;Thank you.  For some reason I hadn't heard of IShellDispatch before.  I'm a bit disappointed that even this moderate degree of complexity is necessary.  I was hoping for something resembling an ordinary DLL that could export methods of an ordinary class, and the DLL's client can just include the .h file and make ordinary calls directly.  The client didn't even have to know that a vtbl is involved, though as C++ programmers we know about it.  Starting now I will think of [dual] as permitting access through either IDispatch or IShellDispatch, but still not really directly through the vtbl.&lt;br&gt;&lt;br&gt;2/6/2004 7:11 AM Paul Bartlett:&lt;br&gt;&lt;br&gt;&amp;gt; I also think that Norman thought dual&lt;br&gt;&amp;gt; interfaces would allow certain parameter&lt;br&gt;&amp;gt; types to be treated differently (he mentions&lt;br&gt;&amp;gt; SAFEARRAY and &amp;quot;unsafe&amp;quot; arrays&lt;br&gt;&lt;br&gt;Yes I was hoping for that.  SAFEARRAYs do get marshalled between the COM DLL's COM interface and callers in Visual Basic, JavaScript, etc.  The DLL's .odl file has to import &amp;quot;oaidl.idl&amp;quot; (which by the way is a different file than MSDN says to import for SAFEARRAY).  But I don't want to force an ordinary C++ client to use SAFEARRAYs just to access my DLL, so I wanted to export a method with pointer and count parameters through the vtbl.  For a plain ordinary DLL without COM that would of course be most straightforward.</description></item><item><title>re: The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#69868</link><pubDate>Mon, 09 Feb 2004 06:37:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:69868</guid><dc:creator>Raymond Chen</dc:creator><description>I guess I don't understand what you mean by &amp;quot;not really directly through the vtbl&amp;quot;. When you write&lt;br&gt;&lt;br&gt;  psd-&amp;gt;ControlPanelItem(bs);&lt;br&gt;&lt;br&gt;you're calling the method through the vtbl, just like any other C++ object.&lt;br&gt;</description></item><item><title>re: The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#70343</link><pubDate>Tue, 10 Feb 2004 03:05:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:70343</guid><dc:creator>Norman Diamond</dc:creator><description>2/8/2004 10:37 PM Raymond Chen:&lt;br&gt;&lt;br&gt;&amp;gt; When you write&lt;br&gt;&amp;gt; psd-&amp;gt;ControlPanelItem(bs);&lt;br&gt;&amp;gt; you're calling the method through the vtbl&lt;br&gt;&lt;br&gt;You're right, so that accomplishes what I said I was asking for.  Mike Dimmick also explained part of it, saying that the #import statement yields knowledge of the vtbl instead of being a clone of Class Wizard's knowledge of the COM interface.  Now when I have time I need to experiment.  I guess I was confused because it was still necessary to call CoCreateInstance() instead of just including a .h file.</description></item><item><title>re: The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#70444</link><pubDate>Tue, 10 Feb 2004 06:15:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:70444</guid><dc:creator>Raymond Chen</dc:creator><description>CoCreateInstance creates the object. If not with CCI, how else would you be able to create the object?  (I guess the .h file could have its own creation function, like DirectDrawCreate, but then you'd also need a .lib to link against.)</description></item><item><title>re: The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#70669</link><pubDate>Tue, 10 Feb 2004 16:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:70669</guid><dc:creator>Mo</dc:creator><description>I think what Norman was getting at (to a point) is something which exports either a set of plain C functions, or a C++ class which effectively wraps a given CoClass in a typelib - i.e., such that the client doesn't have to know anything about COM at all.&lt;br&gt;&lt;br&gt;Perhaps he'd like something like this:&lt;br&gt;&lt;br&gt;  Shell *pshell = new Shell();&lt;br&gt;  pshell-&amp;gt;ControlPanelItem(&amp;quot;Keyboard&amp;quot;);&lt;br&gt;&lt;br&gt;Letting the class constructor deal with the CoCreateInstance() for you.&lt;br&gt;&lt;br&gt;The problem with this is, of course, that the only sane way to do that is to have a stub class which deals with the construction and marshals parameters for you. &lt;br&gt;&lt;br&gt;Alternatively, you could play with deriving the interface structures and add static methods which constructed the COM object for you, giving you something like:&lt;br&gt;&lt;br&gt;ShellDispatch *psd = ShellDispatch::Create();&lt;br&gt;&lt;br&gt;or perhaps:&lt;br&gt;&lt;br&gt;ShellDispatch *psd = Shell::CreateDispatch();&lt;br&gt;&lt;br&gt;But that still leaves you with a few problems; most importantly, you have the fundamental problem of interfaces vs. classes. Do you try and roll all of a CoClass's interfaces into a single C++ class? Or do you have a separate class for each interface? Perhaps you return IShellDispatch like normal, but construct it using a helper class? Whatever your answer, it hasn't really got you very far (and isn't much above calling CoCreateInstance(), besides looking prettier).&lt;br&gt;&lt;br&gt;I guess what would be really nice (and potentially what Norman *might* have been hankering after) was a way of using COM to, for want of a better term, marshal C++ method calls. We all know how to write COM servers in C++ - wouldn't it be nice if the client side looked (from a programming interface point of view) like the servers?&lt;br&gt;&lt;br&gt;The answer to that is a definite maybe. In reality, COM (and I can only assume by design) went out of its way to strike a balance between convenience and extensibility; the clear division between clients and servers, and between interfaces and classes (which are opaque, save for IUnknown, of course), does you an awful lot of favours. It's certainly true that the COM APIs aren't the nicest in the world, but CoCreateInstance isn't too bad, and once you have your instance there's very little reason to touch them throughout the lifetime of the instance.&lt;br&gt;&lt;br&gt;My suggestion: if CoCreateInstance puts you off, wrap it in a macro call:&lt;br&gt;&lt;br&gt;#define CreateShellDispatch(inst) CoCreateInstance(CLSID_Shell, NULL, CLSCTX_ALL, IID_IShellDispatch, &amp;amp;(inst))&lt;br&gt;</description></item><item><title>re: The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#70686</link><pubDate>Tue, 10 Feb 2004 16:40:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:70686</guid><dc:creator>Raymond Chen</dc:creator><description>If the only quibble was having to use CoCreateInstance instead of &amp;quot;new&amp;quot;, then - well - that's what happens when you are designing a language-neutral interoperability system. A wrapper class or helper macro will have to do.&lt;br&gt;&lt;br&gt;If you use IDL to generate your interfaces, then the marshalling is done for you by the MIDL compiler. The catch is that the things you pass need to be MIDL-friendly, but that's unavoidable since MIDL isn't psychic.</description></item><item><title>re: The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#70713</link><pubDate>Tue, 10 Feb 2004 17:25:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:70713</guid><dc:creator>Mo</dc:creator><description>Well, yes, you're completely right (of course). In a system such as COM, you're always going to get a divide between the &amp;quot;ideal&amp;quot; and the &amp;quot;sane&amp;quot;.&lt;br&gt;&lt;br&gt;From experience, the two biggest hurdles for people using COM for the first time seem to be memory management (especially if delving into the shell interfaces) and parameter types. It's not so much that there's anything wrong with the way things are done, more that they're just so different that it takes a little getting used to.&lt;br&gt;&lt;br&gt;Learning COM can often mean throwing out a mindset you've built up using various programming languages and trying to think of the bigger picture - a lot of people doing COM stuff will never ever do anything besides inproc servers, so a few of the things COM makes you do might seem like overkill. Even trying to get your head around why IUnknown even works can be a bit of a leap of faith to begin with :)&lt;br&gt;</description></item><item><title>re: The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#87662</link><pubDate>Thu, 11 Mar 2004 02:42:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:87662</guid><dc:creator>Norman Diamond</dc:creator><description>OK, I think I figured out what I wish for.  It is something less than COM, it is only for in-process servers where marshalling would be trivial.&lt;br&gt;&lt;br&gt;As previously mentioned, the server provides an interface which is accessible from clients in Visual Basic, JavaScript, etc., using their ordinary function or method calls and member variable accesses and &amp;quot;new&amp;quot; operations.&lt;br&gt;&lt;br&gt;The same interface is accessible from clients in Visual C++ through the entire weighty COM client infrastructure.  For out-of-process or distributed servers, of course all this stuff is necessary in order to do the marshalling.  For in-process stuff, besides being overkill, it also overkills ordinary C++ client programmers.  The Class Wizard operation builds helpers that map BSTR* to CString to help make some things easier for C++ clients, but it doesn't understand SAFEARRAY.  #import understands all data types used in the class library but it doesn't build helpers.  CString cannot be used in IDL.&lt;br&gt;&lt;br&gt;For in-process servers with trivial marshalling, C++ clients of ordinary DLLs can do ordinary function or method calls equally simply as Visual Basic programmers can call COM interfaces.  Of course Visual Basic calling COM does have all the execution overhead, but client programmers can write simple code.&lt;br&gt;&lt;br&gt;To provide an in-process server with simple interface access from VC++ clients, it still looks like I have to make a separate DLL from the DLL that serves clients in other languages.  It would be nice if a single DLL could provide an in-process server with trivial marshalling and simple calling from clients in all languages, instead of needing two DLLS.&lt;br&gt;</description></item><item><title>re: The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#87668</link><pubDate>Thu, 11 Mar 2004 02:45:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:87668</guid><dc:creator>Raymond Chen</dc:creator><description>All you have to do now is come up with a language-independent &amp;quot;new&amp;quot; operator - and then you find that you've reinvented CoCreateInstance.&lt;br&gt;&lt;br&gt;I don't see why you need two DLLs for this.  C++ clients can link to a DLL just as well as COM. After all, shell32 exposes some objects (CLSID_ShellLink) through COM and still can export functions (SHGetFileInfo) normally.</description></item><item><title>re: The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#87703</link><pubDate>Thu, 11 Mar 2004 03:44:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:87703</guid><dc:creator>Norman Diamond</dc:creator><description>I put a second interface in the IDL file and corresponding code in the .h and .cpp files, intending to make this an interface for C++ clients.  Up to a point it worked.  But when I added a CString parameter, the MIDL compiler complained.  If I use BSTRs then we're halfway back to the situation where C++ clients have to be overkilled and there's no point having the second interface any more.  (Well, for arrays there might still be a purpose in having the second interface.)&lt;br&gt;&lt;br&gt;Or do you mean that the server's .h and .cpp files can contain additional C++ methods that are not even mentioned in the IDL file?  Then I could tell clients of C++ clients not to use either the Class Wizard or #import, ignore the difficult exported methods and just use the simple ones.  If a C++ client uses the DLL directly and a VB client uses the COM mechanism, both clients will be served properly?</description></item><item><title>re: The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#87714</link><pubDate>Thu, 11 Mar 2004 04:23:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:87714</guid><dc:creator>Raymond Chen</dc:creator><description>Right, MIDL doesn't know how to marshal a CString. It does understand boring LPCWSTR though; that may be good enough.&lt;br&gt;&lt;br&gt;Or you can just put the stuff you don't want MIDL to mess with inside a cpp_quote directive. Then MIDL will just emit it blindly without interpreting it.&lt;br&gt;&lt;br&gt;And yes then you can tell C++ clients to just #include the header file and make direct calls. VB clients can still use the COM mechanism.  Shell32 does this.</description></item><item><title>re: The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#87740</link><pubDate>Thu, 11 Mar 2004 05:44:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:87740</guid><dc:creator>Norman Diamond</dc:creator><description>OK, maybe I've figured it out now.  One DLL can export two classes.  A generic class serves C++ clients and serves an ATL class.  The ATL class serves all other languages.  The generic class must be declared in its own .h file so that C++ clients can #include that one without being forced to understand a COM interface.&lt;br&gt;&lt;br&gt;I still worry that the DLL might get unloaded when the COM usage count goes to 0 and COM doesn't know that the DLL has non-COM clients.&lt;br&gt;&lt;br&gt;Meanwhile, back to the attempted use of #import from a COM interface,&lt;br&gt;&lt;br&gt;&amp;gt; MIDL [...] does understand boring LPCWSTR&lt;br&gt;&lt;br&gt;I neglected to try LPCTSTR.  It knows both of the possible underlying types but does it suit VC++ style to a _T()?&lt;br&gt;&lt;br&gt;&amp;gt; put the stuff you don't want MIDL to mess&lt;br&gt;&amp;gt; with inside a cpp_quote directive&lt;br&gt;&lt;br&gt;I can't figure out what to use it for.  For anything that I want to add to the server and/or make visible to C++ clients, I can just type it into a .h file and MIDL will never see it.</description></item><item><title>re: The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#87744</link><pubDate>Thu, 11 Mar 2004 05:53:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:87744</guid><dc:creator>Raymond Chen</dc:creator><description>If the DLL has non-COM clients they will have done their own LoadLibrary of the target DLL (either by an explicit call to LoadLibrary or implicitly by the loader when it sees the link in the import table), so the DLL reference count will not drop to zero.  Even if COM shows up, it will LoadLibrary you (bring your DLL reference count up to 2), and then FreeLibrary you when it's done, dropping the count to 1 (not zero - so the DLL is not freed).&lt;br&gt;&lt;br&gt;You can't use LPCTSTR in a header file - that means that your function will get passed Unicode strings by Unicode callers and ANSI strings by ANSI callers - and you can't tell which is which. If you want to support both Unicode and ANSI callers you need two functions, one W and one A.&lt;br&gt;&lt;br&gt;Using cpp_quote lets you reduce to two files (foo.idl and foo.h). Otherwise you need three (foo.idl, foo.h, and fooextra.h where fooextra.h contains the C++ interfaces).</description></item><item><title>re: The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#87752</link><pubDate>Thu, 11 Mar 2004 06:14:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:87752</guid><dc:creator>Norman Diamond</dc:creator><description>&amp;gt; Even if COM shows up [...]&lt;br&gt;&lt;br&gt;OK, thank you.&lt;br&gt;&lt;br&gt;&amp;gt; You can't use LPCTSTR in a header file&lt;br&gt;&lt;br&gt;In an IDL file, for the reason you mentioned.  You're right, I still need to supply separate methods to C++ ANSI clients and C++ Unicode clients (besides the separate interface for all non-C languages).&lt;br&gt;&lt;br&gt;&amp;gt; Using cpp_quote lets you reduce to two files&lt;br&gt;&amp;gt; (foo.idl and foo.h).&lt;br&gt;&lt;br&gt;That I don't see.  If foo.idl generates foo.h then foo.h declares a class with its COM interface declaration.  If C++ clients #include foo.h then they will have to understand the entire COM interface declaration even if they don't use it.  I need fooextra.h for C++ clients regardless of whether foo.idl has any cpp_quote stuff.</description></item><item><title>re: The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#87754</link><pubDate>Thu, 11 Mar 2004 06:28:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:87754</guid><dc:creator>Raymond Chen</dc:creator><description>The COM interface declaration is plain C/C++ once you unwrap the macros. Check out objidl.h, for example.</description></item><item><title>re: The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#87766</link><pubDate>Thu, 11 Mar 2004 07:13:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:87766</guid><dc:creator>Norman Diamond</dc:creator><description>&amp;gt; The COM interface declaration is plain C/C++&lt;br&gt;&amp;gt; once you unwrap the macros.&lt;br&gt;&lt;br&gt;Of course, but clients do not automatically include all the header files required for that unwrapping.  I already got lost, trying to hunt down everything that would have to be included for it.  Even though foo.cpp compiles while it's including foo.h, it's pretty hard to make fooclient.cpp compile when it's including foo.h.  It seems to be easier to let fooclient.cpp include fooextra.h instead of foo.h.</description></item><item><title>re: The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#87784</link><pubDate>Thu, 11 Mar 2004 08:25:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:87784</guid><dc:creator>Raymond Chen</dc:creator><description>MIDL automatically sticks the necessary #include directives at the top of the generated .h file. But if you don't like it, then fine, create two .h files.</description></item><item><title>re: The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#87792</link><pubDate>Thu, 11 Mar 2004 08:52:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:87792</guid><dc:creator>Norman Diamond</dc:creator><description>&amp;gt; MIDL automatically sticks the necessary&lt;br&gt;&amp;gt; #include directives at the top of the&lt;br&gt;&amp;gt; generated .h file.&lt;br&gt;&lt;br&gt;I guess VC++ .NET did that for you.  For me, VC++ 6 SP5 sticks some necessary #include directives at the top of foo.h, some buried further down in foo.h, some in StdAfx.h, and some at the top foo.c.  For a client (.exe) it didn't generate as many #include directives as for the server (.dll), and didn't generate all of the needed ones.  It's not a matter of liking it or not, but I kept getting lost when following the chains of #include directives and could not get a client to compile when the client had #include foo.h.</description></item><item><title>re: The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#87794</link><pubDate>Thu, 11 Mar 2004 09:04:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:87794</guid><dc:creator>Raymond Chen</dc:creator><description>foo.c?  stdafx.h?  I was talking about foo.idl and the autogenerated foo.h. At the top of the foo.h that is produced by the MIDL compiler you'll see&lt;br&gt;&lt;br&gt;#include &amp;quot;rpc.h&amp;quot;&lt;br&gt;#include &amp;quot;rpcndr.h&amp;quot;&lt;br&gt;#include &amp;quot;windows.h&amp;quot;&lt;br&gt;#include &amp;quot;ole2.h&amp;quot;&lt;br&gt;&lt;br&gt;These define the macros used by the interface declarations.</description></item><item><title>re: The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#88342</link><pubDate>Fri, 12 Mar 2004 03:40:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:88342</guid><dc:creator>Norman Diamond</dc:creator><description>OK, I wasn't clear when mentioning which #include directives were generated by which parts of VC++ 6.  The MFC DLL wizard generates foo.h and StdAfx.h.  The MIDL compiler generates foo_i.h, foo_i.c, and foo_p.c.&lt;br&gt;&lt;br&gt;When a client's .h file had #include foo.h, it didn't compile.  I kept getting lost while trying to track down other header files that it needed.  From your latest reply I guess I should have tried to #include foo_i.h.&lt;br&gt;&lt;br&gt;Meanwhile I finished making a foo_extra.h and refactored the server.  The COM interface is working for a VB client and the extra class is working for a VC++ client, so my real wish seems to have come true, it's all one DLL.&lt;br&gt;&lt;br&gt;Whether development effort can be further optimized by telling VC++ clients to #include foo_i.h instead of foo_extra.h, I'll experiment again when I have time.&lt;br&gt;&lt;br&gt;Hmm, now I see why cpp_quote can reduce the number of .h files.  Stuff that is presently in foo.h can be fed into foo_i.h through cpp_quote instead.  But then what happens if someone uses the VC++ 6 IDE to add a class member?  Additions to Ifoo go in foo.idl, but additions to Cfoo ordinarily go into foo.h.</description></item><item><title>re: The layout of a COM object</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#88377</link><pubDate>Fri, 12 Mar 2004 05:46:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:88377</guid><dc:creator>Raymond Chen</dc:creator><description>True if you have other tools that munge header files then you can't use cpp_quote. Personally I don't use any of those wizardly things. If I want to edit something, I whip out &amp;quot;vi&amp;quot;.</description></item><item><title>re: How to host an IContextMenu, part 10 - Composite extensions - groundwork</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#239020</link><pubDate>Thu, 07 Oct 2004 04:06:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:239020</guid><dc:creator>The Old New Thing</dc:creator><description /></item><item><title>re: Why does the debugger show me the wrong virtual function?</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#401152</link><pubDate>Wed, 23 Mar 2005 22:52:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:401152</guid><dc:creator>The Old New Thing</dc:creator><description /></item><item><title>re: Why does the debugger show me the wrong virtual function?</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#401158</link><pubDate>Wed, 23 Mar 2005 23:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:401158</guid><dc:creator>The Old New Thing</dc:creator><description /></item><item><title>How Do Script Engines Implement Object Identity?</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#412203</link><pubDate>Tue, 26 Apr 2005 19:55:16 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:412203</guid><dc:creator>Fabulous Adventures In Coding</dc:creator><description>I've talked a few times in this blog about the semantics of the equality operators in various languages....</description></item><item><title>What is the underlying object behind a COM interface pointer?</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#2261604</link><pubDate>Tue, 24 Apr 2007 19:12:14 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2261604</guid><dc:creator>The Old New Thing</dc:creator><description>&lt;p&gt;Use the vtable.&lt;/p&gt;</description></item><item><title>COM in REALbasic</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/02/05/68017.aspx#4910500</link><pubDate>Fri, 14 Sep 2007 16:00:44 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:4910500</guid><dc:creator>Ramblings</dc:creator><description>&lt;p&gt;So in my last entry, I teased you with a hint that you can now work with COM using pure REALbasic code. Today, I'm going to tease you a bit more. ;-) Before you can understand how to write COM...&lt;/p&gt;
</description></item></channel></rss>