Discussion:
IDispatch and dispinterface
(too old to reply)
George
2008-09-13 06:54:03 UTC
Permalink
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
Igor Tandetnik
2008-09-13 15:33:49 UTC
Permalink
Post by George
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?
No. Dispinterface is an IDispatch plus an agreement on what each DISPID
means and what parameters it should come with.
Post by George
And when we declare dispinterface SomeInterce, then it means
SomeInterface inherits from dispinterface interface and dispinterface
inherits from IDispatch?
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
George
2008-09-14 09:30:00 UTC
Permalink
Thanks Igor,
Post by Igor Tandetnik
No. Dispinterface is an IDispatch plus an agreement on what each DISPID
means and what parameters it should come with.
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
SvenC
2008-09-14 10:24:28 UTC
Permalink
Hi George,
Post by Igor Tandetnik
No. Dispinterface is an IDispatch plus an agreement on what each
DISPID means and what parameters it should come with.
it is appreciated if you could describe more about what do you mean
"what each DISPID means and what parameters it should come with"
...
My current confusion is, when we define interface IDispatch, we could
also define DISPID, so does dispinterface add more restrictions to
DISPID defined?
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
George
2008-09-14 12:12:00 UTC
Permalink
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
SvenC
2008-09-14 12:31:08 UTC
Permalink
Hi George,
Post by George
From your description, dispinterface is the only way we could assign
dispid expolicitly?
No, in the dual interface case you assign dispids explicitly as well.
Post by George
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?
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
Post by George
And if we use IDispatch we can not use dispid as in the below sample?
interface UseMeLikeThis : IDispatch
{
[id(1)] BSTR Name;
[id(2)] BSTR SetNewNameReturnOld([in] BSTR newName);
};
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
George
2008-09-14 12:56:06 UTC
Permalink
Thanks SvenC,
Post by SvenC
Search the web for information about adding a dual interface to
an existing dispinterface created and implemented with MFC
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
SvenC
2008-09-14 13:37:35 UTC
Permalink
Hi George,
Post by George
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?
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.
Post by George
2.
If yes, it means dispinterface decribed interface is not dual
interface and only expose IDispatch?
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.
Post by George
[
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);
}
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.
Post by George
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?
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.
Post by George
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 [*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
George
2008-09-16 07:07:01 UTC
Permalink
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
SvenC
2008-09-16 07:39:11 UTC
Permalink
Hi George,
Post by George
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?
Yes.

--
SvenC
George
2008-09-16 07:55:01 UTC
Permalink
Thanks SvenC,
Post by George
dispinterface helloPro {
interface hello;
};
Yes.
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
SvenC
2008-09-16 09:18:53 UTC
Permalink
Hi George,
Post by George
Post by George
dispinterface helloPro {
interface hello;
};
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.
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
George
2008-09-16 10:50:01 UTC
Permalink
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
SvenC
2008-09-16 11:20:23 UTC
Permalink
Hi George,
Post by George
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
{
}
coclass CFoo
{
interface IFoo;
}
Does it mean IFoo derives from IDispatch? If not derived, what is the
internal implementation?
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
George
2008-09-16 11:46:00 UTC
Permalink
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
SvenC
2008-09-16 12:32:13 UTC
Permalink
Hi George,
Post by George
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 ":"
dispinterface ITestFoo : IUnknown{
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
George
2008-09-16 12:44:01 UTC
Permalink
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
SvenC
2008-09-16 13:03:16 UTC
Permalink
Hi George,
Post by George
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).
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
George
2008-09-16 13:29:02 UTC
Permalink
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
George
2008-09-16 07:44:00 UTC
Permalink
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
Igor Tandetnik
2008-09-16 12:01:49 UTC
Permalink
Post by George
Suppose in the following IDL code,
dispinterface ITest1 {
};
coclass Test1
{
interface ITest1;
};
I'm not sure this would compile (though I'm too lazy to test). You might
have to write "dispinterface ITest1;" inside coclass statement.
Post by George
My question is about the derivation hierarchy. Does the above IDL mean
ITest1 derives from IDispatch? Or?
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
George
2008-09-16 12:21:01 UTC
Permalink
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
Igor Tandetnik
2008-09-16 12:45:58 UTC
Permalink
Post by George
I have tried but still compile failed. I am using VS 2008.
This line of code has compile error -- COM_INTERFACE_ENTRY(ITestFoo).
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
George
2008-09-16 13:19:01 UTC
Permalink
Thanks Igor,
Post by Igor Tandetnik
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.
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
Igor Tandetnik
2008-09-16 13:26:11 UTC
Permalink
Post by George
Post by Igor Tandetnik
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.
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
Correct.
Post by George
and only change related C++ file
Yes.
Post by George
(I am using project name TestATL1,
then I should change file TestFoo.h
Yes.
Post by George
TestATL1_i.c and TestATL1_i.h)?
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
George
2008-09-16 13:50:01 UTC
Permalink
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
Igor Tandetnik
2008-09-16 15:38:31 UTC
Permalink
Post by George
[uuid(BFB73347-822A-1068-8849-00DD011087E8), version(1.0),
helpstring("Useful help string."), helpcontext(2480)]
dispinterface IMyDispatch {
[id(1)] int x; // An integer property named x.
[id(2)] BSTR y; // A string property named y.
[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;
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()
};
Post by George
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;
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).
Post by George
3. interface IMyDispatch will derive from IUnknown and have a
different IID from IDispatch;
Well, all interfaces derive from IUnknown and have distinct IIDs. So
yes, this is trivially true.
Post by George
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.
I'm not sure what you mean by "exposed" here. Other than that part, yes,
this is correct.
Post by George
But what is the inheritance relationship between IDispatch and
dispinterface IMyDispatch?
Usually, IMyDispatch simply doesn't exist as a class in your C++
program. You write IDispatch instead.
Post by George
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?
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.
Post by George
What I am not sure is whether in the vtable of IMyDispatch, x, y,
show and computeit should be included?
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
Igor Tandetnik
2008-09-16 15:41:59 UTC
Permalink
Post by George
[uuid(BFB73347-822A-1068-8849-00DD011087E8), version(1.0),
helpstring("Useful help string."), helpcontext(2480)]
dispinterface IMyDispatch {
[id(1)] int x; // An integer property named x.
[id(2)] BSTR y; // A string property named y.
[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;
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()
};
Post by George
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;
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).
Post by George
3. interface IMyDispatch will derive from IUnknown and have a
different IID from IDispatch;
Well, all interfaces derive from IUnknown and have distinct IIDs. So
yes, this is trivially true.
Post by George
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.
I'm not sure what you mean by "exposed" here. Other than that part, yes,
this is correct.
Post by George
But what is the inheritance relationship between IDispatch and
dispinterface IMyDispatch?
Usually, IMyDispatch simply doesn't exist as a class in your C++
program. You write IDispatch instead.
Post by George
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?
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.
Post by George
What I am not sure is whether in the vtable of IMyDispatch, x, y,
show and computeit should be included?
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
George
2008-09-17 06:30:01 UTC
Permalink
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
Igor Tandetnik
2008-09-17 12:20:32 UTC
Permalink
Post by George
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?
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
George
2008-09-17 12:50:00 UTC
Permalink
Thanks Igor,
Post by Igor Tandetnik
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?
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
Igor Tandetnik
2008-09-17 13:03:31 UTC
Permalink
Post by George
Post by Igor Tandetnik
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?
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.
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?
Post by George
In this way, COM consumer could consume
dispinterface like dual interface.
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.
Post by George
My question is, if I provide vtable based access
for dispinterface IMyDispatch, like show method, ATL and COM does not
prohibits this, correct?
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
George
2008-09-17 13:25:01 UTC
Permalink
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
unknown
2010-01-13 21:30:50 UTC
Permalink
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" <***@discussions.microsoft.com> wrote in messag news:A2D16814-CE3D-4780-ACF5-***@microsoft.co

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 Tandetni

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 exactl
and produce a more meaningful type library, so that e.g. your developmen
system (VC++, VB, VBA...) can use that information to produce C+
class wrappers or intellisense while you are typing

Lets take a sample

coclass YourComponen

[default] interface IDispatch
}

The above is perfectly valid but it gives neither your development syste
nor you as a developer any hints which dispids can be used and whic
parameters are valid

dispinterface UseMeLikeThi

properties
[id(1)] BSTR Name
methods
[id(2)] BSTR SetNewNameReturnOld([in] BSTR newName)
}

coclass YourComponent

dispinterface UseMeLikeThis
}

For YourComponent2 your development system can provide mor
intellisense

Nevertheless, both components can implement their Invoke method
for IDispatch to accept undocumented DISPIDs as well. You coul
use this to implement "secret features"

Dual interfaces are also describing their methods and propertie
and add the additional benefit of vtable access for programmin
languages like C++ to make calling methods and properties mor
efficient than using combinations of GetIDsFromNames an
Invoke where you additionally need to build a variant array t
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" <***@discussions.microsoft.com> wrote in message news:23EA611A-6FC3-4660-A67F-***@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 TestATL1Li

importlib("stdole2.tlb")

uuid(DFB61153-34AC-4475-9A99

67BE29E410FC)
helpstring("TestFoo Class"

coclass TestFo

dispinterface ITestFoo
}
}

class ATL_NO_VTABLE CTestFoo
public

CComObjectRootEx<CComSingleThreadModel>
public CComCoClass<CTestFoo,

&CLSID_TestFoo>
public ITestFo

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 whic
behave like an IDispatch interface. When you implement
component which exposes a dispinterface you will need t
expose IDispatch and should implement GetIdsFromNames an
Invoke in a way that matches your properties/methods

IIRC ATL does not add any help for implementing dispinterface
instead it assumes you are using dual interfaces instead which ca
be implemented easily with the help of IDispatchImpl

But it might be a good exercise for you to develop a workin
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.

(31) : error C2552: 'ATL::_ATL_INTMAP_ENTRY::piid' :

non-aggregates cannot be initialized with initializer lis

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 TestATL1Li

importlib("stdole2.tlb")

uuid(DFB61153-34AC-4475-9A99

67BE29E410FC)
helpstring("TestFoo Class"

coclass TestFo

dispinterface ITestFoo
}
}

class ATL_NO_VTABLE CTestFoo
public

CComObjectRootEx<CComSingleThreadModel>
public CComCoClass<CTestFoo,

&CLSID_TestFoo>
public ITestFo

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" <***@discussions.microsoft.com> wrote in messag news:563CCD22-73CA-412B-8895-***@microsoft.co

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 Tandetni

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 fo
implementing dispinterfaces instead it assumes you are usin
dual interfaces instead which can be implemented easily wit
the help of IDispatchImpl

[me, now] Seems that I did remember that correctly

See if your book ATL internals does help on implementin
dispinterfaces with the help of ATL. If you find nothing the
either implement it on your own in plain C++ or leav
dispinterfaces and go with a dual interface and IDispatchImp

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" <***@discussions.microsoft.com> wrote in message news:ECC7628C-E246-4172-A140-***@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 <***@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 <***@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" <***@discussions.microsoft.com> wrote in message news:96B3AE79-F8D0-4AED-98D4-***@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" <***@discussions.microsoft.com> wrote in message news:75322256-2F72-43FD-B52F-***@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
Tim Roberts
2010-01-15 05:45:49 UTC
Permalink
Post by unknown
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
GetIDsofNames() and Invoke() (besides GetTypeInfo() and
GetTypeInfoCount() which are used to read type info at runtime).
What there a question in this 1300-line posting, which you actually sent
twice?
--
Tim Roberts, ***@probo.com
Providenza & Boekelheide, Inc.
zubin polra
2011-12-27 10:12:27 UTC
Permalink
I have got an interface pointer from COM-Mathod(suppose mathod-A).
I want to pass it to another mathod(suppose mathod-B) as an argument.

mathod-B has been succedded but the work has not been done.

My actual task is: "Create a Rule to Move Specific E-mails to a Folder" in outlook 2007 using outlook object model.


mathod-A:TargetFolder = dispFolders.InvokeMethod("Add", VarSpam, arg);
mathod-B:dispMoveToFolder.SetProperty("Folder", *TargetFolder);

here TargetFolder is pointer to 'VARIANT' struct.
dispFolders and dispMoveToFolder are object of my class.
invoke() mathod of my class call IDispatch::Invoke() by substituting proper arguments such as disp-id etc. and return VARIANT * as return value to me.

same as above SetProperty of my class also call IDispatch::Invoke().

my third mathod:dispRules.InvokeMethod("Save", arg); fails telling me that exception occurred:(exceptin's text like: "one or more conditions ar actions are not properly saved")

thus i knew that mathod-B has not done work properyly despite of succedded.

what is the problem?
Please guide me.
Post by George
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
Post by Igor Tandetnik
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
Post by George
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
Post by SvenC
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.
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
{
[id(1)] BSTR Name;
[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
Post by George
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
{
[id(1)] BSTR Name;
[id(2)] BSTR SetNewNameReturnOld([in] BSTR newName);
};
coclass YourComponent2
{
dispinterface UseMeLikeThis;
};
regards,
George
Post by SvenC
Hi George,
No, in the dual interface case you assign dispids explicitly as well.
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
Post by George
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
Post by SvenC
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
Post by George
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
Post by SvenC
Hi George,
Yes.
--
SvenC
Post by George
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 {
};
coclass Test1
{
interface ITest1;
};
My question is about the derivation hierarchy. Does the above IDL mean
ITest1 derives from IDispatch? Or?
regards,
George
Post by George
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
Post by SvenC
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
Post by George
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
{
}
coclass CFoo
{
interface IFoo;
}
Does it mean IFoo derives from IDispatch? If not derived, what is the
internal implementation?
regards,
George
Post by SvenC
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
Post by George
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
Post by Igor Tandetnik
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
Post by George
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).
1>d:\visual studio 2008\projects\testatl1\testatl1\testfoo.h
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;
};
};
public
CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CTestFoo,
&CLSID_TestFoo>,
public ITestFoo
{
CTestFoo()
{
}
DECLARE_REGISTRY_RESOURCEID(IDR_TESTFOO)
BEGIN_COM_MAP(CTestFoo)
COM_INTERFACE_ENTRY(ITestFoo)
END_COM_MAP()
regards,
George
Post by SvenC
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
Post by George
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).
1>d:\visual studio 2008\projects\testatl1\testatl1\testfoo.h
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;
};
};
public
CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CTestFoo,
&CLSID_TestFoo>,
public ITestFoo
{
CTestFoo()
{
}
DECLARE_REGISTRY_RESOURCEID(IDR_TESTFOO)
BEGIN_COM_MAP(CTestFoo)
COM_INTERFACE_ENTRY(ITestFoo)
END_COM_MAP()
regards,
George
Post by Igor Tandetnik
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
Post by SvenC
Hi George,
[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
Post by George
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
Post by Igor Tandetnik
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
Post by George
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 {
[id(1)] int x; // An integer property named x.
[id(2)] BSTR y; // A string property named y.
[id(3)] void show(); // No arguments, no result.
[id(11)] int computeit(int inarg, double *outarg);
};
regards,
George
Post by George
Thanks Igor!
I have thought carefully about your reply, some more point to confirm before
coding.
Interface like below, will actually,
[uuid(BFB73347-822A-1068-8849-00DD011087E8), version(1.0),
helpstring("Useful help string."), helpcontext(2480)]
dispinterface IMyDispatch {
[id(1)] int x; // An integer property named x.
[id(2)] BSTR y; // A string property named y.
[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
Post by Igor Tandetnik
You'd typically expose both. It would actually be the same interface -
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
Post by Igor Tandetnik
You'd typically expose both. It would actually be the same interface -
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
Post by George
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?
[uuid(BFB73347-822A-1068-8849-00DD011087E8), version(1.0),
helpstring("Useful help string."), helpcontext(2480)]
dispinterface IMyDispatch {
[id(1)] int x; // An integer property named x.
[id(2)] BSTR y; // A string property named y.
[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
Post by Igor Tandetnik
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
Post by George
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
Post by Igor Tandetnik
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
Post by George
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
Post by unknown
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
GetIDsofNames() and Invoke() (besides GetTypeInfo() and
GetTypeInfoCount() which are used to read type info at runtime).
Post by unknown
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).
For Excel - COM example,
http://shaktisaran.tech.officelive.com/ExcelCOM.aspx
Post by Tim Roberts
What there a question in this 1300-line posting, which you actually sent
twice?
--
Providenza & Boekelheide, Inc.
unknown
2010-01-13 21:36:34 UTC
Permalink
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).

For Excel - COM example,
http://shaktisaran.tech.officelive.com/ExcelCOM.aspx



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" <***@discussions.microsoft.com> wrote in messag news:A2D16814-CE3D-4780-ACF5-***@microsoft.co

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 Tandetni

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 exactl
and produce a more meaningful type library, so that e.g. your developmen
system (VC++, VB, VBA...) can use that information to produce C+
class wrappers or intellisense while you are typing

Lets take a sample

coclass YourComponen

[default] interface IDispatch
}

The above is perfectly valid but it gives neither your development syste
nor you as a developer any hints which dispids can be used and whic
parameters are valid

dispinterface UseMeLikeThi

properties
[id(1)] BSTR Name
methods
[id(2)] BSTR SetNewNameReturnOld([in] BSTR newName)
}

coclass YourComponent

dispinterface UseMeLikeThis
}

For YourComponent2 your development system can provide mor
intellisense

Nevertheless, both components can implement their Invoke method
for IDispatch to accept undocumented DISPIDs as well. You coul
use this to implement "secret features"

Dual interfaces are also describing their methods and propertie
and add the additional benefit of vtable access for programmin
languages like C++ to make calling methods and properties mor
efficient than using combinations of GetIDsFromNames an
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" <***@discussions.microsoft.com> wrote in message news:23EA611A-6FC3-4660-A67F-***@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 ITestFo

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 whic
behave like an IDispatch interface. When you implement
component which exposes a dispinterface you will need t
expose IDispatch and should implement GetIdsFromNames an
Invoke in a way that matches your properties/methods

IIRC ATL does not add any help for implementing dispinterface
instead it assumes you are using dual interfaces instead which ca
be implemented easily with the help of IDispatchImpl

But it might be a good exercise for you to develop a workin
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.

(31) : error C2552: 'ATL::_ATL_INTMAP_ENTRY::piid' :

non-aggregates cannot be initialized with initializer lis

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 TestATL1Li

importlib("stdole2.tlb")

uuid(DFB61153-34AC-4475-9A99

67BE29E410FC)
helpstring("TestFoo Class"

coclass TestFo

dispinterface ITestFoo
}
}

class ATL_NO_VTABLE CTestFoo
public

CComObjectRootEx<CComSingleThreadModel>
public CComCoClass<CTestFoo,

&CLSID_TestFoo>
public ITestFo

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" <***@discussions.microsoft.com> wrote in messag news:563CCD22-73CA-412B-8895-***@microsoft.co

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 Tandetni

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 fo
implementing dispinterfaces instead it assumes you are usin
dual interfaces instead which can be implemented easily wit
the help of IDispatchImpl

[me, now] Seems that I did remember that correctly

See if your book ATL internals does help on implementin
dispinterfaces with the help of ATL. If you find nothing the
either implement it on your own in plain C++ or leav
dispinterfaces and go with a dual interface and IDispatchImp

Uups, somehow I got out of WaitForSingleObject(hPicture
INFINITE) without having been signalled. Somebody must hav
redefined my INFINITE - recompiled, going back to sleep..

-
Sven
-
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" <***@discussions.microsoft.com> wrote in message news:ECC7628C-E246-4172-A140-***@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 <***@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 <***@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" <***@discussions.microsoft.com> wrote in message news:96B3AE79-F8D0-4AED-98D4-***@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" <***@discussions.microsoft.com> wrote in message news:75322256-2F72-43FD-B52F-***@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

On Wednesday, January 13, 2010 4:30 PM
Shakti Saran wrote:

IDispatch and dispinterface
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).


Submitted via EggHeadCafe - Software Developer Portal of Choice
Secure Session State Transfer: ASP to ASP.NET
http://www.eggheadcafe.com/tutorials/aspnet/19f8d04a-6bce-4ee0-8d6e-1ef18cbb92e1/secure-session-state-tran.aspx
Loading...