From: Shakti on
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