How to implement several interface by one C++ class in VS7 ATL project 
Author Message
 How to implement several interface by one C++ class in VS7 ATL project

Dear Experts:
    One simple question:
    I create  a ATL project in VS7 and I add a ATL simple object, which will
create one c++ class and implement one interface.
    If I want this class to implement other interface, how can I do? In VC 6
I can define the number of interface to implement when I add the class, but
I can not find this in VS7.

You kind suggestion will be appreciated.

Zhipeng Liu



Sun, 06 Mar 2005 15:34:25 GMT  
 How to implement several interface by one C++ class in VS7 ATL project
Example to follow:

[export, uuid(8DA258E7-515D-4f3c-92ED-0AD7E1665FCA)]
struct ASDF_TYPE
{
    [helpstring("Val1")] BSTR Val1;

Quote:
};

[
        object,
        uuid("96662C57-3F83-42e9-9153-2D98A55883B1"),
        dual,   helpstring("Iasdf Interface"),
        pointer_default(unique)
]
__interface Iasdf1 : IDispatch
{
    [ id( 1), helpstring("") ] HRESULT Foo( [in] BSTR sInput, [out,
retval] struct ASDF_TYPE *pAsdf );

Quote:
};

[
        object,
        uuid("BCC4E3E1-146F-43af-8D52-A3909AA1F376"),
        dual,   helpstring("Iasdf2 Interface"),
        pointer_default(unique)
]
__interface Iasdf2 : IDispatch
{
    HRESULT Foo( [in] struct ASDF_TYPE *pAsdf, [out, retval] BSTR
*psRetval );
    HRESULT FooEx( [out, retval, satype(struct ASDF_TYPE)] SAFEARRAY
**ppudt );

Quote:
};

[
        coclass,
        threading("free"),
        support_error_info("Iasdf2"),
    support_error_info("Iasdf1"),
    default(Iasdf),
    com_interface_entry("COM_INTERFACE_ENTRY2(IDispatch, Iasdf1)"),
        vi_progid("TestInterfaces.TestTwoInterfaces"),
        progid("TestInterfaces.TestTwoInterfaces.1"),
    aggregatable(never),
        version(1.0),
        uuid("51CE8CE5-320B-46CC-B379-86005E8D74C5"),
        custom(TLBATTR_TRANS_NOTSUPP,0),
        helpstring("TestTwoInterfaces Class")
]
class ATL_NO_VTABLE CTestTwoInterfaces :
        public IObjectControl,
        public IObjectConstruct,
        public Iasdf1,
    public Iasdf2
{
public:
        CTestTwoInterfaces()
        {
        }

        DECLARE_PROTECT_FINAL_CONSTRUCT()

        HRESULT FinalConstruct()
        {
                return S_OK;
        }

        void FinalRelease()
        {
        }

// IObjectControl
public:
        STDMETHOD(Activate)();
        STDMETHOD_(BOOL, CanBePooled)();
        STDMETHOD_(void, Deactivate)();

        CComPtr<IObjectContext> m_spObjectContext;
        STDMETHOD(Construct)(IDispatch * pCtorObj)
        {
                CComPtr<IObjectConstructString> spObjectConstructString;
                HRESULT hr = pCtorObj->QueryInterface(&spObjectConstructString);
                if (SUCCEEDED(hr))
                {
                        CComBSTR bstrConstruct;
                        hr = spObjectConstructString->get_ConstructString(&bstrConstruct);
                        if (SUCCEEDED(hr))
                        {
                                // TODO : Use the string to construct the object.
                        }
                }
                return hr;
        }

public:
    STDMETHOD(Iasdf1::Foo)(BSTR sInput, struct ASDF_TYPE *pAsdf);
    STDMETHOD(Iasdf2::Foo)(struct ASDF_TYPE *pAsdf, BSTR *psRetval);
    STDMETHOD(FooEx)( SAFEARRAY **ppudt );

Quote:
};

> Dear Experts:
>     One simple question:
>     I create  a ATL project in VS7 and I add a ATL simple object, which will
> create one c++ class and implement one interface.
>     If I want this class to implement other interface, how can I do? In VC 6
> I can define the number of interface to implement when I add the class, but
> I can not find this in VS7.

> You kind suggestion will be appreciated.

> Zhipeng Liu



Sun, 06 Mar 2005 23:33:10 GMT  
 How to implement several interface by one C++ class in VS7 ATL project
Your example presents two dual interfaces implemented
on the same object which is contrary to COM laws. I suggest
you change one of the interfaces to derive from IUnknown
instead.

--
=====================================
Alexander Nickolov
Microsoft MVP [VC], MCSD

MVP VC FAQ: http://www.mvps.org/vcfaq
=====================================

Quote:

> Example to follow:

> [export, uuid(8DA258E7-515D-4f3c-92ED-0AD7E1665FCA)]
> struct ASDF_TYPE
> {
>     [helpstring("Val1")] BSTR Val1;
> };

> [
> object,
> uuid("96662C57-3F83-42e9-9153-2D98A55883B1"),
> dual, helpstring("Iasdf Interface"),
> pointer_default(unique)
> ]
> __interface Iasdf1 : IDispatch
> {
>     [ id( 1), helpstring("") ] HRESULT Foo( [in] BSTR sInput, [out,
> retval] struct ASDF_TYPE *pAsdf );
> };

> [
> object,
> uuid("BCC4E3E1-146F-43af-8D52-A3909AA1F376"),
> dual, helpstring("Iasdf2 Interface"),
> pointer_default(unique)
> ]
> __interface Iasdf2 : IDispatch
> {
>     HRESULT Foo( [in] struct ASDF_TYPE *pAsdf, [out, retval] BSTR
> *psRetval );
>     HRESULT FooEx( [out, retval, satype(struct ASDF_TYPE)] SAFEARRAY
> **ppudt );
> };

> [
> coclass,
> threading("free"),
> support_error_info("Iasdf2"),
>     support_error_info("Iasdf1"),
>     default(Iasdf),
>     com_interface_entry("COM_INTERFACE_ENTRY2(IDispatch, Iasdf1)"),
> vi_progid("TestInterfaces.TestTwoInterfaces"),
> progid("TestInterfaces.TestTwoInterfaces.1"),
>     aggregatable(never),
> version(1.0),
> uuid("51CE8CE5-320B-46CC-B379-86005E8D74C5"),
> custom(TLBATTR_TRANS_NOTSUPP,0),
> helpstring("TestTwoInterfaces Class")
> ]
> class ATL_NO_VTABLE CTestTwoInterfaces :
> public IObjectControl,
> public IObjectConstruct,
> public Iasdf1,
>     public Iasdf2
> {
> public:
> CTestTwoInterfaces()
> {
> }

> DECLARE_PROTECT_FINAL_CONSTRUCT()

> HRESULT FinalConstruct()
> {
> return S_OK;
> }

> void FinalRelease()
> {
> }

> // IObjectControl
> public:
> STDMETHOD(Activate)();
> STDMETHOD_(BOOL, CanBePooled)();
> STDMETHOD_(void, Deactivate)();

> CComPtr<IObjectContext> m_spObjectContext;
> STDMETHOD(Construct)(IDispatch * pCtorObj)
> {
> CComPtr<IObjectConstructString> spObjectConstructString;
> HRESULT hr = pCtorObj->QueryInterface(&spObjectConstructString);
> if (SUCCEEDED(hr))
> {
> CComBSTR bstrConstruct;
> hr = spObjectConstructString->get_ConstructString(&bstrConstruct);
> if (SUCCEEDED(hr))
> {
> // TODO : Use the string to construct the object.
> }
> }
> return hr;
> }

> public:
>     STDMETHOD(Iasdf1::Foo)(BSTR sInput, struct ASDF_TYPE *pAsdf);
>     STDMETHOD(Iasdf2::Foo)(struct ASDF_TYPE *pAsdf, BSTR *psRetval);
>     STDMETHOD(FooEx)( SAFEARRAY **ppudt );
> };


> > Dear Experts:
> >     One simple question:
> >     I create  a ATL project in VS7 and I add a ATL simple object, which will
> > create one c++ class and implement one interface.
> >     If I want this class to implement other interface, how can I do? In VC 6
> > I can define the number of interface to implement when I add the class, but
> > I can not find this in VS7.

> > You kind suggestion will be appreciated.

> > Zhipeng Liu



Mon, 07 Mar 2005 02:37:20 GMT  
 How to implement several interface by one C++ class in VS7 ATL project
I don't believe its contrary to COM laws to having 2 dual interfaces, its
just that IDispatchImpl doesn't implement things correctly if you inherit
from it more than once.   Granted, its not advisable to expose more than one
dual interface, but there are ways to do it right:
http://www.sellsbrothers.com/tools/multidisp/

I believe if you use attribution in ATL 7, it does the multiple duals
correctly.

-Daniel


Your example presents two dual interfaces implemented
on the same object which is contrary to COM laws. I suggest
you change one of the interfaces to derive from IUnknown
instead.

--
=====================================
Alexander Nickolov
Microsoft MVP [VC], MCSD

MVP VC FAQ: http://www.mvps.org/vcfaq
=====================================


Quote:
> Example to follow:

> [export, uuid(8DA258E7-515D-4f3c-92ED-0AD7E1665FCA)]
> struct ASDF_TYPE
> {
>     [helpstring("Val1")] BSTR Val1;
> };

> [
> object,
> uuid("96662C57-3F83-42e9-9153-2D98A55883B1"),
> dual, helpstring("Iasdf Interface"),
> pointer_default(unique)
> ]
> __interface Iasdf1 : IDispatch
> {
>     [ id( 1), helpstring("") ] HRESULT Foo( [in] BSTR sInput, [out,
> retval] struct ASDF_TYPE *pAsdf );
> };

> [
> object,
> uuid("BCC4E3E1-146F-43af-8D52-A3909AA1F376"),
> dual, helpstring("Iasdf2 Interface"),
> pointer_default(unique)
> ]
> __interface Iasdf2 : IDispatch
> {
>     HRESULT Foo( [in] struct ASDF_TYPE *pAsdf, [out, retval] BSTR
> *psRetval );
>     HRESULT FooEx( [out, retval, satype(struct ASDF_TYPE)] SAFEARRAY
> **ppudt );
> };

> [
> coclass,
> threading("free"),
> support_error_info("Iasdf2"),
>     support_error_info("Iasdf1"),
>     default(Iasdf),
>     com_interface_entry("COM_INTERFACE_ENTRY2(IDispatch, Iasdf1)"),
> vi_progid("TestInterfaces.TestTwoInterfaces"),
> progid("TestInterfaces.TestTwoInterfaces.1"),
>     aggregatable(never),
> version(1.0),
> uuid("51CE8CE5-320B-46CC-B379-86005E8D74C5"),
> custom(TLBATTR_TRANS_NOTSUPP,0),
> helpstring("TestTwoInterfaces Class")
> ]
> class ATL_NO_VTABLE CTestTwoInterfaces :
> public IObjectControl,
> public IObjectConstruct,
> public Iasdf1,
>     public Iasdf2
> {
> public:
> CTestTwoInterfaces()
> {
> }

> DECLARE_PROTECT_FINAL_CONSTRUCT()

> HRESULT FinalConstruct()
> {
> return S_OK;
> }

> void FinalRelease()
> {
> }

> // IObjectControl
> public:
> STDMETHOD(Activate)();
> STDMETHOD_(BOOL, CanBePooled)();
> STDMETHOD_(void, Deactivate)();

> CComPtr<IObjectContext> m_spObjectContext;
> STDMETHOD(Construct)(IDispatch * pCtorObj)
> {
> CComPtr<IObjectConstructString> spObjectConstructString;
> HRESULT hr = pCtorObj->QueryInterface(&spObjectConstructString);
> if (SUCCEEDED(hr))
> {
> CComBSTR bstrConstruct;
> hr = spObjectConstructString->get_ConstructString(&bstrConstruct);
> if (SUCCEEDED(hr))
> {
> // TODO : Use the string to construct the object.
> }
> }
> return hr;
> }

> public:
>     STDMETHOD(Iasdf1::Foo)(BSTR sInput, struct ASDF_TYPE *pAsdf);
>     STDMETHOD(Iasdf2::Foo)(struct ASDF_TYPE *pAsdf, BSTR *psRetval);
>     STDMETHOD(FooEx)( SAFEARRAY **ppudt );
> };




- Show quoted text -

Quote:
> > Dear Experts:
> >     One simple question:
> >     I create  a ATL project in VS7 and I add a ATL simple object, which
will
> > create one c++ class and implement one interface.
> >     If I want this class to implement other interface, how can I do? In
VC 6
> > I can define the number of interface to implement when I add the class,
but
> > I can not find this in VS7.

> > You kind suggestion will be appreciated.

> > Zhipeng Liu



Mon, 07 Mar 2005 07:07:44 GMT  
 How to implement several interface by one C++ class in VS7 ATL project
Oh no, not multiple dual interfaces argument again! This has been
discussed a thousand times already - multiple dual interfaces on the
same object violate COM identity rules.

See

http://msdn.microsoft.com/library/en-us/wss/wss/_exchsv2k_frequently_ask
ed_questions.asp

Allow me to quote:

<quote>
How can CDO objects expose multiple dual interfaces?

The short answer is: they can't. By definition, a dual interface is one
that both extends the IDispatch interface and provides access to defined
methods through the v-table and through the seven methods defined by the
IDispatch interface (hence the name dual). Because Component Object
Model (COM) uses proxy/stubs to marshal arguments between separate
apartments, objects can expose only one IDispatch interface. In
addition, you can't trick COM proxy/stubs by returning different
addresses depending upon the interface from which you request IDispatch
(for more details on this rule, see Advanced ). Therefore, there's one
and only one IDispatch interface per object.

If the client calls from a separate COM apartment (or process, or even
machine process), COM silently provides a proxy and stub manager to
remote the calls. The client is then invoking methods through interfaces
aggregated on the proxy object, not directly on the object itself. The
proxy rigorously enforces the COM object identity laws and additionally
assumes that there is only one address for each interface exposed by the
object. Being unaware of the devious attempt to return "appropriate"
IDispatch physical addresses in round-robin fashion to the client, it
instead preempts us, always returning the first IDispatch address
retrieved by the client, and regardless of how this interface is
subsequently requested. To circumvent this behavior, we are forced to
return interfaces exposed on different object identities (and,
therefore, through different proxy objects) to get the new IDispatch
address (through the new proxy object) to the client in the other
apartment.
</quote>

--
With best wishes,
    Igor Tandetnik

"For every complex problem, there is a solution that is simple, neat,
and wrong." H.L. Mencken


Quote:
> I don't believe its contrary to COM laws to having 2 dual interfaces,
its
> just that IDispatchImpl doesn't implement things correctly if you
inherit
> from it more than once.   Granted, its not advisable to expose more
than one
> dual interface, but there are ways to do it right:
> http://www.sellsbrothers.com/tools/multidisp/

> I believe if you use attribution in ATL 7, it does the multiple duals
> correctly.

> -Daniel



> Your example presents two dual interfaces implemented
> on the same object which is contrary to COM laws. I suggest
> you change one of the interfaces to derive from IUnknown
> instead.

> --
> =====================================
> Alexander Nickolov
> Microsoft MVP [VC], MCSD

> MVP VC FAQ: http://www.mvps.org/vcfaq
> =====================================



> > Example to follow:

> > [export, uuid(8DA258E7-515D-4f3c-92ED-0AD7E1665FCA)]
> > struct ASDF_TYPE
> > {
> >     [helpstring("Val1")] BSTR Val1;
> > };

> > [
> > object,
> > uuid("96662C57-3F83-42e9-9153-2D98A55883B1"),
> > dual, helpstring("Iasdf Interface"),
> > pointer_default(unique)
> > ]
> > __interface Iasdf1 : IDispatch
> > {
> >     [ id( 1), helpstring("") ] HRESULT Foo( [in] BSTR sInput, [out,
> > retval] struct ASDF_TYPE *pAsdf );
> > };

> > [
> > object,
> > uuid("BCC4E3E1-146F-43af-8D52-A3909AA1F376"),
> > dual, helpstring("Iasdf2 Interface"),
> > pointer_default(unique)
> > ]
> > __interface Iasdf2 : IDispatch
> > {
> >     HRESULT Foo( [in] struct ASDF_TYPE *pAsdf, [out, retval] BSTR
> > *psRetval );
> >     HRESULT FooEx( [out, retval, satype(struct ASDF_TYPE)] SAFEARRAY
> > **ppudt );
> > };

> > [
> > coclass,
> > threading("free"),
> > support_error_info("Iasdf2"),
> >     support_error_info("Iasdf1"),
> >     default(Iasdf),
> >     com_interface_entry("COM_INTERFACE_ENTRY2(IDispatch, Iasdf1)"),
> > vi_progid("TestInterfaces.TestTwoInterfaces"),
> > progid("TestInterfaces.TestTwoInterfaces.1"),
> >     aggregatable(never),
> > version(1.0),
> > uuid("51CE8CE5-320B-46CC-B379-86005E8D74C5"),
> > custom(TLBATTR_TRANS_NOTSUPP,0),
> > helpstring("TestTwoInterfaces Class")
> > ]
> > class ATL_NO_VTABLE CTestTwoInterfaces :
> > public IObjectControl,
> > public IObjectConstruct,
> > public Iasdf1,
> >     public Iasdf2
> > {
> > public:
> > CTestTwoInterfaces()
> > {
> > }

> > DECLARE_PROTECT_FINAL_CONSTRUCT()

> > HRESULT FinalConstruct()
> > {
> > return S_OK;
> > }

> > void FinalRelease()
> > {
> > }

> > // IObjectControl
> > public:
> > STDMETHOD(Activate)();
> > STDMETHOD_(BOOL, CanBePooled)();
> > STDMETHOD_(void, Deactivate)();

> > CComPtr<IObjectContext> m_spObjectContext;
> > STDMETHOD(Construct)(IDispatch * pCtorObj)
> > {
> > CComPtr<IObjectConstructString> spObjectConstructString;
> > HRESULT hr = pCtorObj->QueryInterface(&spObjectConstructString);
> > if (SUCCEEDED(hr))
> > {
> > CComBSTR bstrConstruct;
> > hr = spObjectConstructString->get_ConstructString(&bstrConstruct);
> > if (SUCCEEDED(hr))
> > {
> > // TODO : Use the string to construct the object.
> > }
> > }
> > return hr;
> > }

> > public:
> >     STDMETHOD(Iasdf1::Foo)(BSTR sInput, struct ASDF_TYPE *pAsdf);
> >     STDMETHOD(Iasdf2::Foo)(struct ASDF_TYPE *pAsdf, BSTR *psRetval);
> >     STDMETHOD(FooEx)( SAFEARRAY **ppudt );
> > };



> > > Dear Experts:
> > >     One simple question:
> > >     I create  a ATL project in VS7 and I add a ATL simple object,
which
> will
> > > create one c++ class and implement one interface.
> > >     If I want this class to implement other interface, how can I
do? In
> VC 6
> > > I can define the number of interface to implement when I add the
class,
> but
> > > I can not find this in VS7.

> > > You kind suggestion will be appreciated.

> > > Zhipeng Liu



Mon, 07 Mar 2005 07:30:52 GMT  
 
 [ 5 post ] 

 Relevant Pages 

1. How to Implement more than one Sink/Event Interface [ATL]

2. Implementing multiple interfaces from one class...

3. VS6 C++ project makes VS7 crash on project load

4. Howto Expose a normal C++ class with methods via an Interface Class in ATL COM

5. Book recommendations for VS7 *ATL Server* projects?

6. Implementing Events in your C++ classes/interfaces

7. Create one singleton object in other interface's method (in one project)

8. Sinking one interface from several sources

9. Getting one of several Interfaces in a COM object

10. Internal Compiler Error while deriving C# class from a MC++ class implementing a C# interface

11. Can't add more than one ATL object to an ATL project using wizard

12. One propertysheet for several classes

 

 
Powered by phpBB® Forum Software