From: Shakti on 13 Jan 2010 16:30 When a coclass wishes to allow late-bound clients to access its functionality, it must support COM interface named IDispatch. This standard COM interface allows a late-bound client to call any method or property on the object's IDispatch implementation (termed a dispinterface) using two well-known methods: GetIDsofNames() and Invoke() (besides GetTypeInfo() and GetTypeInfoCount() which are used to read type info at runtime). Georg wrote: IDispatch and dispinterface 13-Sep-08 Hello everyone, 1. I read some MSDN document and some other forum discussions about the differences between IDispatch and dispinterface, but still confused. From MSDN, dispinterface is another interface inherits from IDispatch? 2. And when we declare dispinterface SomeInterce, then it means SomeInterface inherits from dispinterface interface and dispinterface inherits from IDispatch? thanks in advance, George Previous Posts In This Thread: On Saturday, September 13, 2008 2:54 AM Georg wrote: IDispatch and dispinterface Hello everyone, 1. I read some MSDN document and some other forum discussions about the differences between IDispatch and dispinterface, but still confused. From MSDN, dispinterface is another interface inherits from IDispatch? 2. And when we declare dispinterface SomeInterce, then it means SomeInterface inherits from dispinterface interface and dispinterface inherits from IDispatch? thanks in advance, George On Saturday, September 13, 2008 11:33 AM Igor Tandetnik wrote: Re: IDispatch and dispinterface "George" <George(a)discussions.microsoft.com> wrote in message news:A2D16814-CE3D-4780-ACF5-43F2A9332F16(a)microsoft.com No. Dispinterface is an IDispatch plus an agreement on what each DISPID means and what parameters it should come with. This question makes no sense to me, sorry. -- With best wishes, Igor Tandetnik With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925 On Sunday, September 14, 2008 5:30 AM Georg wrote: Thanks Igor,I found MSDN does not cover too much of what you mentioned above. Thanks Igor, I found MSDN does not cover too much of what you mentioned above. It is appreciated if you could describe more about what do you mean "what each DISPID means and what parameters it should come with" or recommend some documents for me to learn? :-) My current confusion is, when we define interface IDispatch, we could also define DISPID, so does dispinterface add more restrictions to DISPID defined? regards, George On Sunday, September 14, 2008 6:24 AM SvenC wrote: Hi George,dispinterface is useful to describe your IDispatch interface more Hi George, dispinterface is useful to describe your IDispatch interface more exactly and produce a more meaningful type library, so that e.g. your development system (VC++, VB, VBA...) can use that information to produce C++ class wrappers or intellisense while you are typing. Lets take a sample: coclass YourComponent { [default] interface IDispatch; }; The above is perfectly valid but it gives neither your development system nor you as a developer any hints which dispids can be used and which parameters are valid. dispinterface UseMeLikeThis { properties: [id(1)] BSTR Name; methods: [id(2)] BSTR SetNewNameReturnOld([in] BSTR newName); }; coclass YourComponent2 { dispinterface UseMeLikeThis; }; For YourComponent2 your development system can provide more intellisense. Nevertheless, both components can implement their Invoke methode for IDispatch to accept undocumented DISPIDs as well. You could use this to implement "secret features". Dual interfaces are also describing their methods and properties and add the additional benefit of vtable access for programming languages like C++ to make calling methods and properties more efficient than using combinations of GetIDsFromNames and Invoke where you additionally need to build a variant array to pass method parameters. So there is typically some extra conversion from your native param types to and from variants. My recommendation: develop *and use* various different COM components with IDispatch only, dispinterface or dual. See for yourself what the differences are for you as developer of the component and for you as a developer using the component. It seems to me that this is the only way that you might start to understand why COM is like it is. Don't take it personally but I have to say that your last topics are quite basic COM knowledge and I think they are not too difficult. If it takes you so long to understand them then either we are really bad explainers or you need to take a different approach to learn them. You always seem to try understanding a technique without any "problem" in mind which you want to solve. It seems to me that this approach is not too successful. If you take a look at scenarios where COM is used and how those scenarios make use of coclasses, CLSIDs, progids, interfaces, dispinterfaces, proxy/stub, marshalling and so on, then you might learn more about COM than now. So give yourself tasks like "develop a COM component which does <fill this with some useful function for your needs> and is usable from C++, VBA and VBS". Develop a component which only exposes a custom interface (only inherits IUnknown not IDispatch). Use that component from C++ with the help of #import. Now try to use the component in VBA and VBS. See what works and what not. See if adding IDispatch helps. See what happens when you have parameters which are not automation compatible. E.g. some structs or char*. So learn from mistakes and especially from solving mistakes. -- SvenC On Sunday, September 14, 2008 8:12 AM Georg wrote: Thanks SvenC,1. Thanks SvenC, 1. From your description, dispinterface is the only way we could assign dispid expolicitly? 2. "The above is perfectly valid but it gives neither your development system nor you as a developer any hints which dispids can be used and which parameters are valid." -- I agree the approach using dispinterface hints which dispids can be used. But what do you mean "which parameters are valid" -- type of each parameter are clearly defined in the IDL. Could you help to clarify please? 3. And if we use IDispatch we can not use dispid as in the below sample? interface UseMeLikeThis : IDispatch { properties: [id(1)] BSTR Name; methods: [id(2)] BSTR SetNewNameReturnOld([in] BSTR newName); }; coclass YourComponent2 { dispinterface UseMeLikeThis; }; regards, George On Sunday, September 14, 2008 8:31 AM SvenC wrote: Hi George,No, in the dual interface case you assign dispids explicitly as well. Hi George, No, in the dual interface case you assign dispids explicitly as well. Think again about my IDL content: coclass YourComponent { [default] interface IDispatch; }; With the above content you say only "my coclass YourComponent exposes IDispatch". You do *not* specify any additional interface. So where do specify valid dispids? My answer: you cannot to it. You need some additional "information carrier" in your idl. And that is dispinterface or dual interfaces As far as I know that is simply invalid syntax. You cannot use the keywords properties and methods in an interface but only in dispinterface Search the web for information about adding a dual interface to an existing dispinterface created and implemented with MFC wizards. There you see how to go from odl and dispinterface to idl and interface. That should clarify how dispinterface definitions differ from interface definitions. -- SvenC On Sunday, September 14, 2008 8:56 AM Georg wrote: Thanks SvenC,I have did some web search for how to assign dispid for dual Thanks SvenC, I have did some web search for how to assign dispid for dual interface, like this. As you said, to assign dispid we only have two ways, either assign interface as dispinterface, or assign the interface as dual. 1. My further question is, dispinterface and dual interface is exclusive of each other, i.e. when we assign dual, we can not assign dispinterface, and vice versa? 2. If yes, it means dispinterface decribed interface is not dual interface and only expose IDispatch? [ object, dual, uuid(D544BFC1-BC81-11d0-A982-00AA00C0177B), helpstring("Itest Interface") ] interface Itest : IDispatch { [id(1), helpstring("method TestLong")] HRESULT TestLong([in] long parm1, [out,retval] long *ret); [id(2), helpstring("method TestString")] HRESULT TestString([in] BSTR str, [out,retval] BSTR *ret); } 3. You mentioned -- "The above is perfectly valid but it gives neither your development system nor you as a developer any hints which dispids can be used and which parameters are valid." -- I agree the approach using dispinterface hints which dispids can be used. But what do you mean "which parameters are valid" -- even without dispinterface, type of each parameter are clearly defined in the IDL. Could you help to clarify please? regards, George On Sunday, September 14, 2008 9:37 AM SvenC wrote: Hi George,Why don't you try it yourself? Hi George, Why don't you try it yourself? Try to define an interface which derives from IDispatch and a dispinterface and put them both in a coclass coclass YourComponent3 { interface IYourDual; dispinterface IYourDisp; }; Try if using the [default] attrib on interface or dispinterface can be used. Try if it makes a difference if you keep IYourDual and IYourDisp in sync as you keep the same properties, methods and parameters. In my eyes the knowledge you gain by those tests is "not relevant in production code". I would never consider using stuff just for the sake of "using that stuff". Those are corner cases where you are responsible to read and understand all the contract details defined by COM and OLE automation in this scenario to still be able to develop correct components. But you also count on your component clients (the other developers and their developer tools) to know all the corner cases as well. Otherwise you might use a corner case correctly which another dev didn't care about and causes an error. If there is no need for the corner case: "code defensively" to not force such errors. Please, try to use an exact wording. From the above sentence I do not know if you are just a careless writer or if you really didn't get the point fully! A better statement in my eyes is: s coclass exposing just a dispinterface can only be used through IDispatch and IUnknown. [please, don't ask how to use properties and methods of your dispinterface with IUnknown. You cannot and you should know by know!] A dispinterface does not expose IDispatch. Your coclass which exposes a dispinterface "indicates" that the C++ class you implement should *not* return E_NOINTERFACE when a client calls its QueryInterface for IID_IDispatch. *BUT* the idl and the created typelibrary is "just a contract" which you show to your clients. You can happily break that contract by implementing QueryInterface to return NULL for every IID the client is QI'ing for. That component is of course of no great value to anybody and IIRC refusing to return a valid IUnknown implementation when QI'ed for IID_IUnknown is "breaking the COM law". Please try to understand the difference between a contract (idl, typelibrary) and its implementation in the programming language of your choice which should of course be able to let you create valid COM components. Why did you give the above sample code? Again: no offense intended. I just don't understand if it belongs to your statement 2 or 3 and how it gives meaningful information to 2 or 3. I simply post the answer for dispids two posts earlier and replace just dispid with parameters. Don't you think you should have come up with that on your own? Please, think harder and more careful. With the above content you say only "my coclass YourComponent exposes IDispatch". You do not specify any additional interface. So where do specify valid dispids [*added*] and property names and their data types and methods and their parameter types. My answer: you cannot to it. You need some additional "information carrier" in your idl. And that is dispinterface or dual interfaces -- SvenC On Tuesday, September 16, 2008 3:07 AM Georg wrote: Hi SvenC,I did more study today by reading and experimenting MSDN samples. Hi SvenC, I did more study today by reading and experimenting MSDN samples. http://msdn.microsoft.com/en-us/library/ms221599.aspx For the 2nd grammar, dispinterface helloPro { interface hello; }; It is mentioned in MSDN -- "TUsing Syntax 2, interfaces that support IDispatch and are declared earlier in an Object Definition Language (ODL) script can be redeclared as IDispatch interfaces." My confusion is what means interfaces that support support IDispatch? Means interfaces that derives from IDispatch or? regards, George On Tuesday, September 16, 2008 3:39 AM SvenC wrote: Hi George,Yes.--SvenC Hi George, Yes. -- SvenC On Tuesday, September 16, 2008 3:44 AM Georg wrote: Sorry for interrupting for this thread again, Igor. Sorry for interrupting for this thread again, Igor. :-) After some further study, I still have a question about dispinterface. Suppose in the following IDL code, dispinterface ITest1 { properties: methods: }; coclass Test1 { interface ITest1; }; My question is about the derivation hierarchy. Does the above IDL mean ITest1 derives from IDispatch? Or? regards, George On Tuesday, September 16, 2008 3:55 AM Georg wrote: Thanks SvenC, My confusion is for the above sample, if hello is already Thanks SvenC, My confusion is for the above sample, if hello is already derived from IDispatch, why we need to re-declare it as dispinterface? Even if we do not re-declare, since hello already derives from IDispatch, we could use its function by Invoke. regards, George On Tuesday, September 16, 2008 5:18 AM SvenC wrote: Hi George,It is simply a convenient way to define a dispinterface when you Hi George, It is simply a convenient way to define a dispinterface when you have an existing IDispatch derived custom interface. Someone may or may not have good reasons to expose a dispinterface in parallel to a dual interface. -- SvenC On Tuesday, September 16, 2008 6:50 AM Georg wrote: Thanks SvenC,I think from your description, dispinterface should have the same Thanks SvenC, I think from your description, dispinterface should have the same vtable with IDispatch. I am still confused how it is implemented internally. Suppose I have the following code, dispinterface IFoo { properties: methods: } coclass CFoo { interface IFoo; } Does it mean IFoo derives from IDispatch? If not derived, what is the internal implementation? regards, George On Tuesday, September 16, 2008 7:20 AM SvenC wrote: Hi George,What else as deriving from IDispatch would make sense? Hi George, What else as deriving from IDispatch would make sense? Try it and 1) add at least one property or method to IFoo 2) let the compiler tell you what he thinks about your code 3) write a test app which uses your component and see what happens when you call the property or method I don't know in which olther ways I can express what I recommend to: think about something and then do it! You always seem to stop after the "think about" step. -- SvenC On Tuesday, September 16, 2008 7:46 AM Georg wrote: Thanks SvenC,I have tried before. Thanks SvenC, I have tried before. In my understanding, every interface must be derived from IUnknown, and the same to dispinterface, which should also declare it derives from IUnknown. But seems the grammar is not correct? Compile error is TestATL1.idl(16) : error MIDL2025 : syntax error : expecting ; or { near ":" import "oaidl.idl"; import "ocidl.idl"; [ object, uuid(BFA48DFC-FB86-4799-8118-0459ED969B6E), helpstring("ITestFoo Interface"), pointer_default(unique) ] dispinterface ITestFoo : IUnknown{ }; [ uuid(8F5B7505-D805-4DF6-8943-3486AE3DE3D8), version(1.0), helpstring("TestATL1 1.0 Type Library") ] library TestATL1Lib { importlib("stdole2.tlb"); [ uuid(DFB61153-34AC-4475-9A99-67BE29E410FC), helpstring("TestFoo Class") ] coclass TestFoo { [default] interface ITestFoo; }; }; regards, George On Tuesday, September 16, 2008 8:01 AM Igor Tandetnik wrote: Re: IDispatch and dispinterface "George" <George(a)discussions.microsoft.com> wrote in message news:23EA611A-6FC3-4660-A67F-4E95428960CF(a)microsoft.com I'm not sure this would compile (though I'm too lazy to test). You might have to write "dispinterface ITest1;" inside coclass statement. No. ITest1 is essentially a synonym for IDispatch, with the same seven methods taking all the same parameters, but with a different IID. -- With best wishes, Igor Tandetnik With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925 On Tuesday, September 16, 2008 8:21 AM Georg wrote: Thanks Igor,I have tried but still compile failed. I am using VS 2008. Thanks Igor, I have tried but still compile failed. I am using VS 2008. This line of code has compile error -- COM_INTERFACE_ENTRY(ITestFoo). Compile error is: 1>d:\visual studio 2008\projects\testatl1\testatl1\testfoo.h (31) : error C2552: 'ATL::_ATL_INTMAP_ENTRY::piid' : non-aggregates cannot be initialized with initializer list I posted the whole IDL and part of related source codes here. import "oaidl.idl"; import "ocidl.idl"; [ uuid(BFA48DFC-FB86-4799-8118- 0459ED969B6E), helpstring("ITestFoo Interface") ] dispinterface ITestFoo{ }; [ uuid(8F5B7505-D805-4DF6-8943- 3486AE3DE3D8), version(1.0), helpstring("TestATL1 1.0 Type Library") ] library TestATL1Lib { importlib("stdole2.tlb"); [ uuid(DFB61153-34AC-4475-9A99- 67BE29E410FC), helpstring("TestFoo Class") ] coclass TestFoo { dispinterface ITestFoo; }; }; class ATL_NO_VTABLE CTestFoo : public CComObjectRootEx<CComSingleThreadModel>, public CComCoClass<CTestFoo, &CLSID_TestFoo>, public ITestFoo { public: CTestFoo() { } DECLARE_REGISTRY_RESOURCEID(IDR_TESTFOO) BEGIN_COM_MAP(CTestFoo) COM_INTERFACE_ENTRY(ITestFoo) END_COM_MAP() regards, George On Tuesday, September 16, 2008 8:32 AM SvenC wrote: Hi George,dispinterfaces can be treated as special interface type whichbehave Hi George, dispinterfaces can be treated as special interface type which behave like an IDispatch interface. When you implement a component which exposes a dispinterface you will need to expose IDispatch and should implement GetIdsFromNames and Invoke in a way that matches your properties/methods. IIRC ATL does not add any help for implementing dispinterfaces instead it assumes you are using dual interfaces instead which can be implemented easily with the help of IDispatchImpl. But it might be a good exercise for you to develop a working component which implements a dispinterface with pure C++ from ground up. -- SvenC On Tuesday, September 16, 2008 8:44 AM Georg wrote: Thanks SvenC,I think the best way to see what dispinterface looks like is to Thanks SvenC, I think the best way to see what dispinterface looks like is to write code. I have tried but still compile failed. I am using VS 2008. This line of code has compile error -- COM_INTERFACE_ENTRY(ITestFoo). Compile error is: 1>d:\visual studio 2008\projects\testatl1\testatl1\testfoo.h (31) : error C2552: 'ATL::_ATL_INTMAP_ENTRY::piid' : non-aggregates cannot be initialized with initializer list I posted the whole IDL and part of related source codes here. import "oaidl.idl"; import "ocidl.idl"; [ uuid(BFA48DFC-FB86-4799-8118- 0459ED969B6E), helpstring("ITestFoo Interface") ] dispinterface ITestFoo{ }; [ uuid(8F5B7505-D805-4DF6-8943- 3486AE3DE3D8), version(1.0), helpstring("TestATL1 1.0 Type Library") ] library TestATL1Lib { importlib("stdole2.tlb"); [ uuid(DFB61153-34AC-4475-9A99- 67BE29E410FC), helpstring("TestFoo Class") ] coclass TestFoo { dispinterface ITestFoo; }; }; class ATL_NO_VTABLE CTestFoo : public CComObjectRootEx<CComSingleThreadModel>, public CComCoClass<CTestFoo, &CLSID_TestFoo>, public ITestFoo { public: CTestFoo() { } DECLARE_REGISTRY_RESOURCEID(IDR_TESTFOO) BEGIN_COM_MAP(CTestFoo) COM_INTERFACE_ENTRY(ITestFoo) END_COM_MAP() regards, George On Tuesday, September 16, 2008 8:45 AM Igor Tandetnik wrote: Re: IDispatch and dispinterface "George" <George(a)discussions.microsoft.com> wrote in message news:563CCD22-73CA-412B-8895-8CCC86ACBEEB(a)microsoft.com Dispinterfaces don't appear in the MIDL-generated header file. Just derive your class from IDispatch, and use COM_INTERFACE_ENTRY_IID to map ITestFoo's IID to IDispatch. You will have to define the IID manually - unfortunately, it doesn't appear in the generated header, either. -- With best wishes, Igor Tandetnik With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925 On Tuesday, September 16, 2008 9:03 AM SvenC wrote: Re: IDispatch and dispinterface Hi George, Reread my complete post and find this sentence: [me, one post ago] IIRC ATL does not add any help for implementing dispinterfaces instead it assumes you are using dual interfaces instead which can be implemented easily with the help of IDispatchImpl. [me, now] Seems that I did remember that correctly. See if your book ATL internals does help on implementing dispinterfaces with the help of ATL. If you find nothing then either implement it on your own in plain C++ or leave dispinterfaces and go with a dual interface and IDispatchImpl Uups, somehow I got out of WaitForSingleObject(hPicture, INFINITE) without having been signalled. Somebody must have redefined my INFINITE - recompiled, going back to sleep... -- SvenC -- SvenC On Tuesday, September 16, 2008 9:19 AM Georg wrote: Thanks Igor,I am happy to follow your help to do practices. Thanks Igor, I am happy to follow your help to do practices. But a little confused about your above statements. You mean no need to change IDL file, and keep the IDL file the same as below content as we discussed before -- and only change related C++ file (I am using project name TestATL1, then I should change file TestFoo.h TestATL1_i.c and TestATL1_i.h)? import "oaidl.idl"; import "ocidl.idl"; [ uuid(BFA48DFC-FB86-4799-8118- 0459ED969B6E), helpstring("ITestFoo Interface") ] dispinterface ITestFoo{ }; [ uuid(8F5B7505-D805-4DF6-8943- 3486AE3DE3D8), version(1.0), helpstring("TestATL1 1.0 Type Library") ] library TestATL1Lib { importlib("stdole2.tlb"); [ uuid(DFB61153-34AC-4475-9A99- 67BE29E410FC), helpstring("TestFoo Class") ] coclass TestFoo { dispinterface ITestFoo; }; }; regards, George On Tuesday, September 16, 2008 9:26 AM Igor Tandetnik wrote: Re: IDispatch and dispinterface "George" <George(a)discussions.microsoft.com> wrote in message news:ECC7628C-E246-4172-A140-272BABBD06F1(a)microsoft.com Correct. Yes. Yes. No - these are automatically generated. -- With best wishes, Igor Tandetnik With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925 On Tuesday, September 16, 2008 9:29 AM Georg wrote: Thanks SvenC,Have a good sleep. Thanks SvenC, Have a good sleep. I have a further comment, you can reply tomorrow. :-) Interface like below, will actually, 1. expose the interface IMyDispatch, and not expose IDispatch; 2. and interface IMyDispatch will expose the 4 methods in IDispatch with the same methods' name/signature, in additional to the methods/properties defined below -- like x, y and show; 3. interface IMyDispatch will derive from IUnknown and have a different IID from IDispatch; 4. the methods and properties of dispinterface IMyDispatch will not be invoked by vtable of IMyDispatch, but invoked by Invoke method, even if the methods like x, y and show are exposed. All my above understandings are correct? But what is the inheritance relationship between IDispatch and dispinterface IMyDispatch? No inheritance relationship -- means dispinterface IMyDispatch is not derived from IDispatch? [uuid(BFB73347-822A-1068-8849-00DD011087E8), version(1.0), helpstring("Useful help string."), helpcontext(2480)] dispinterface IMyDispatch { properties: [id(1)] int x; // An integer property named x. [id(2)] BSTR y; // A string property named y. methods: [id(3)] void show(); // No arguments, no result. [id(11)] int computeit(int inarg, double *outarg); }; regards, George On Tuesday, September 16, 2008 9:50 AM Georg wrote: Thanks Igor! Thanks Igor! I have thought carefully about your reply, some more point to confirm before coding. Interface like below, will actually, Code: [uuid(BFB73347-822A-1068-8849-00DD011087E8), version(1.0), helpstring("Useful help string."), helpcontext(2480)] dispinterface IMyDispatch { properties: [id(1)] int x; // An integer property named x. [id(2)] BSTR y; // A string property named y. methods: [id(3)] void show(); // No arguments, no result. [id(11)] int computeit(int inarg, double *outarg); }; 1. expose the interface IMyDispatch, and not expose IDispatch; 2. and interface IMyDispatch will expose the 4 methods in IDispatch with the same methods' name/signature, in additional to the methods/properties defined below -- like x, y and show; 3. interface IMyDispatch will derive from IUnknown and have a different IID from IDispatch; 4. the methods and properties of dispinterface IMyDispatch will not be invoked by vtable of IMyDispatch, but invoked by Invoke method, even if the methods like x, y and show are exposed. All my above understandings are correct? But what is the inheritance relationship between IDispatch and dispinterface IMyDispatch? No inheritance relationship -- means dispinterface IMyDispatch is not derived from IDispatch, they are just totally two different interfaces without any inheritance relationship, just expose the same 4 methods -- GetTypeInfoCount/GetTypeInfo/GetIDsOfNames/Invoke? What I am not sure is whether in the vtable of IMyDispatch, x, y, show and computeit should be included? regards, George On Tuesday, September 16, 2008 11:38 AM Igor Tandetnik wrote: Re: IDispatch and dispinterface George <George(a)discussions.microsoft.com> wrote: You'd typically expose both. It would actually be the same interface - IDispatch - made available by two different IIDs. Like this: class MyClass : public IDispatch, ... { BEGIN_COM_MAP(MyClass) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY_IID(IID_IMyDispatch, IDispatch) END_COM_MAP() }; The terminology may be confusing, as the term "method" here has two different meanings. A regular COM interface method is a slot in that interface's vtable. A dispinterface method is a DISPID plus an agreement of which parameters should be passed along with that DISPID. A dispinterface has 7 (seven) COM methods in its vtable (the same ones IDispatch has). It can support an arbitrary number of dispinterface methods (and properties: a property is really just a pair of methods - a getter and a setter - sharing the same DISPID). This line in the IDL [id(3)] void show(); simply means that a) When your implementation of IDispatch::GetIdsOfNames is called with "show" as a parameter, it will produce a DISPID of 3. b) Your implementation of IDispatch::Invoke can be called passing a DISPID of 3 and no parameters in DISPPARAMS (and will presumably do something reasonable and useful when thus called; at least, it won't fail with DISP_E_MEMBERNOTFOUND error). Well, all interfaces derive from IUnknown and have distinct IIDs. So yes, this is trivially true. I'm not sure what you mean by "exposed" here. Other than that part, yes, this is correct. Usually, IMyDispatch simply doesn't exist as a class in your C++ program. You write IDispatch instead. You could, in principle, do it this way, but I don't quite see why you would want to. You could also derive IMyDispatch from IDispatch and leave it otherwise empty - though again, I don't see the point. Simply use IDispatch everywhere, it already specifies the correct vtable layout, which is all you need on C++ side of things. Din't you just say, in your item #4, that they shouldn't? -- With best wishes, Igor Tandetnik With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925 On Tuesday, September 16, 2008 11:41 AM Igor Tandetnik wrote: Re: IDispatch and dispinterface George <George(a)discussions.microsoft.com> wrote: You'd typically expose both. It would actually be the same interface - IDispatch - made available by two different IIDs. Like this: class MyClass : public IDispatch, ... { BEGIN_COM_MAP(MyClass) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY_IID(IID_IMyDispatch, IDispatch) END_COM_MAP() }; The terminology may be confusing, as the term "method" here has two different meanings. A regular COM interface method is a slot in that interface's vtable. A dispinterface method is a DISPID value plus an agreement of which parameters should be passed along with that DISPID. A dispinterface has 7 (seven) COM methods in its vtable (the same ones IDispatch has). It can support an arbitrary number of dispinterface methods (and properties: a property is really just a pair of methods - a getter and a setter - sharing the same DISPID). This line in the IDL [id(3)] void show(); simply means that a) When your implementation of IDispatch::GetIdsOfNames is called with "show" as a parameter, it will produce a DISPID of 3. b) Your implementation of IDispatch::Invoke can be called passing a DISPID of 3 and no parameters in DISPPARAMS (and will presumably do something reasonable and useful when thus called; at least, it won't fail with DISP_E_MEMBERNOTFOUND error). Well, all interfaces derive from IUnknown and have distinct IIDs. So yes, this is trivially true. I'm not sure what you mean by "exposed" here. Other than that part, yes, this is correct. Usually, IMyDispatch simply doesn't exist as a class in your C++ program. You write IDispatch instead. You could, in principle, do it this way, but I don't quite see why you would want to. You could also derive IMyDispatch from IDispatch and leave it otherwise empty - though again, I don't see the point. Simply use IDispatch everywhere, it already specifies the correct vtable layout, which is all you need on C++ side of things. Din't you just say, in your item #4, that they shouldn't? -- With best wishes, Igor Tandetnik With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925 On Wednesday, September 17, 2008 2:30 AM Georg wrote: Thanks Igor,Two more comments after some experiments.1. Thanks Igor, Two more comments after some experiments. 1. In my sample code below in IDL, even if I provide vtable based access (QueryInterface for dispinterface IMyDispatch, and with IMyDispatch pointer retrieved, call its method like x, y and show) for methods in dispinterface, like methods x,y and show, ATL and COM does not prohibits this, correct? Is there any rules or best practices whether we should expose methods in vtable for a dispinterface? Code: [uuid(BFB73347-822A-1068-8849-00DD011087E8), version(1.0), helpstring("Useful help string."), helpcontext(2480)] dispinterface IMyDispatch { properties: [id(1)] int x; // An integer property named x. [id(2)] BSTR y; // A string property named y. methods: [id(3)] void show(); // No arguments, no result. [id(11)] int computeit(int inarg, double *outarg); }; 2. I feel the only value of dispinterface is, we could explicitly assign dispid for method/property. - If we declare a customized interface derived from IDispatch and not define dual, we can not explicitly assign dispid for method/property; - If we declare a customized interface derived from IDispatch and also marked as dual, we can explicitly assign dispid for method/property. All of the above are correct? :-) regards, George On Wednesday, September 17, 2008 8:20 AM Igor Tandetnik wrote: Re: IDispatch and dispinterface "George" <George(a)discussions.microsoft.com> wrote in message news:96B3AE79-F8D0-4AED-98D4-88E09BFE9EFE(a)microsoft.com I don't understand. How precisely do you plan to "provide vtable based access" for methods in dispinterface? Wouldn't you have to turn it into dual interface? -- With best wishes, Igor Tandetnik With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925 On Wednesday, September 17, 2008 8:50 AM Georg wrote: Thanks Igor,What I mean is when COM consumer QueryInterface for IMyDispatch, Thanks Igor, What I mean is when COM consumer QueryInterface for IMyDispatch, it returns vtable pointer (i.e. interface pointer), the vtable contains not only the 7 methods in IDispatch, but also methods show and computeit from vtable. In this way, COM consumer could consume dispinterface like dual interface. My question is, if I provide vtable based access for dispinterface IMyDispatch, like show method, ATL and COM does not prohibits this, correct? Is there any rules or best practices whether we should expose methods other than the 3 methods in IDispatch in vtable for a dispinterface interface? regards, George On Wednesday, September 17, 2008 9:03 AM Igor Tandetnik wrote: Re: IDispatch and dispinterface "George" <George(a)discussions.microsoft.com> wrote in message news:75322256-2F72-43FD-B52F-F124EAADD7C6(a)microsoft.com Then, by definition, IMyDispatch is not a dispinterface, and it looks very much like a dual interface. Why then not just declare it as such? No. In this way, the interface _is_ a dual interface. If it walks like a duck, and quacks like a duck, it's a duck. No. COM even has a special term to describe such an interface - "dual". -- With best wishes, Igor Tandetnik With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925 On Wednesday, September 17, 2008 9:25 AM Georg wrote: Thanks Igor,Your points are more reasonable than mine. Thanks Igor, Your points are more reasonable than mine. :-) I feel the only value of dispinterface is, we could explicitly assign dispid for method/property. - If we declare a customized interface derived from IDispatch and not define dual, we can not explicitly assign dispid for method/property -- IDL grammar does not allow this; - If we declare a customized interface derived from IDispatch and also marked as dual, we can explicitly assign dispid for method/property. All of the above are correct? :-) regards, George Submitted via EggHeadCafe - Software Developer Portal of Choice File Upload Control Using Silverlight http://www.eggheadcafe.com/tutorials/aspnet/099b9829-514c-47f3-bce1-4149e4482d51/file-upload-control-using.aspx
|
Pages: 1 Prev: Prob with Modal popup dialog. Next: WAVEHDR allocationg several buffers |