Solved

Directx clone function (com/ole knowledge)

Posted on 1998-12-21
4
383 Views
Last Modified: 2013-11-25
i added the documentation of the clone function of directx
object.
i don't understand the third parameter.
it might be connected to com/ole stuff. ( i assume it does.)

can you help ?

IDirect3DRMObject2::Clone
--------------------------------------------------------------------------------

IDirect3DRMObject2
Creates a copy of an object.

Syntax

HRESULT Clone(  LPUNKNOWN pUnkOuter,  REFIID riid,  LPVOID
*ppvObj  );
Parameters

pUnkOuter
Pointer to the outer IUnknown interface that allows COM aggregation
features.
riid
Identifier of the object being copied.
ppvObj
Address that will contain the copy of the object when the method returns.



0
Comment
Question by:hed
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
  • 2
4 Comments
 
LVL 86

Accepted Solution

by:
jkr earned 50 total points
ID: 1180772
It indeed has to do with COM. The mechanism is like this:
IDispatch* m_pObj;

    m_sc    =   ::CoCreateInstance  (   m_clsid,    
                                        NULL,
                                        CLSCTX_SERVER,
                                        IID_IDispatch,
                                        ( void**) &m_pObj
                                    );

In other words: You pass in the address of a pointer in which the address of the newly created object will be stored...
0
 

Author Comment

by:hed
ID: 1180773
sorry.
quite stupid of me.
the third parameter is obvious.
it's the first parameter is the one that puzzles me.
what is
Pointer to the outer IUnknown interface that allows COM aggregation features.
sorry again.
raising to 30.
0
 
LVL 86

Expert Comment

by:jkr
ID: 1180774
The 'outer' IUnknown is used for 'aggregation' (that's the way COM realizes inheritance).
From the VC5 docs:
Begin quote-->
Aggregation
Aggregation is the other, richer, reuse mechanism, in which the outer object exposes interfaces from the inner object as if they were implemented on the outer object itself. This is useful when the outer object would always delegate every call to one of its interfaces to the same interface in the inner object. Aggregation is actually a specialized case of containment/delegation, and is available as a convenience to avoid extra implementation overhead in the outer object in these cases.

Aggregation is almost as simple to implement as containment is, except for the three IUnknown functions: QueryInterface, AddRef, and Release. The catch is that from the client’s perspective, any IUnknown function on the outer object must affect the outer object. That is, AddRef and Release affect the outer object and QueryInterface exposes all the interfaces available on the outer object. However, if the outer object simply exposes an inner object’s interface as its own, that inner object’s IUnknown members called through that interface will behave differently than those IUnknown members on the outer object’s interfaces, an absolute violation of the rules and properties governing IUnknown.

The solution is that aggregation requires an explicit implementation of IUnknown on the inner object and delegation of the IUnknown methods of any other interface to the outer object’s IUnknown methods.

Creating Aggregable Objects
Creating objects that can be aggregated is optional; however, it is simple to do and to do so has significant benefits. The following rules apply to creating an aggregable object:

· The aggregable (or inner) object’s implementation of IUnknown::QueryInterface, AddRef, and Release controls the inner object’s reference count, and this implementation must not delegate to the outer object’s unknown (the controlling IUnknown).

· The QueryInterface, AddRef, and Release methods of all other interfaces implemented on the inner object must delegate to the controlling IUnknown and not directly affect the inner object’s reference count.

· The inner IUnknown must implement QueryInterface only for the inner object.

· The aggregable object must not call AddRef when holding a reference to the controlling IUnknown pointer.

· When the object is created, if any interface other than IUnknown is requested, the creation must fail with E_UNKNOWN.

The code fragment below illustrates a correct implementation of an aggregable object using the nested class method of implementing interfaces:

// CSomeObject is an aggregable object that implements
// IUnknown and ISomeInterface
class CSomeObject : public IUnknown
{
    private:
        DWORD        m_cRef;         // Object reference count
        IUnknown*    m_pUnkOuter;    // Controlling IUnknown, no AddRef
 
        // Nested class to implement the ISomeInterface interface
        class CImpSomeInterface : public ISomeInterface
        {
            friend class CSomeObject ;
            private:
                DWORD    m_cRef;    // Interface ref-count, for debugging
                IUnknown*    m_pUnkOuter;    // controlling IUnknown
            public:
                CImpSomeInterface() { m_cRef = 0;   };
                ~ CImpSomeInterface(void) {};
 
                // IUnknown members delegate to the outer unknown
                // IUnknown members do not control lifetime of object
                STDMETHODIMP     QueryInterface(REFIID riid, void** ppv)
                {    return m_pUnkOuter->QueryInterface(riid,ppv);   };
 
                STDMETHODIMP_(DWORD) AddRef(void)
                {    return m_pUnkOuter->AddRef();   };
 
                STDMETHODIMP_(DWORD) Release(void)
                {    return m_pUnkOuter->Release();   };
 
                // ISomeInterface members
                STDMETHODIMP SomeMethod(void)
                {    return S_OK;   };
        } ;
        CImpSomeInterface m_ImpSomeInterface ;
    public:
        CSomeObject(IUnknown * pUnkOuter)
        {
            m_cRef=0;
            // No AddRef necessary if non-NULL as we're aggregated.
            m_pUnkOuter=pUnkOuter;
            m_ImpSomeInterface.m_pUnkOuter=pUnkOuter;
        } ;
        ~CSomeObject(void) {} ;
 
        // Static member function for creating new instances (don’t use
        // new directly).Protects against outer objects asking for interfaces
        // other than IUnknown
        static HRESULT Create(IUnknown* pUnkOuter, REFIID riid, void **ppv)
        {
            CSomeObject*        pObj;
            if (pUnkOuter != NULL && riid != IID_IUnknown)
                return CLASS_E_NOAGGREGATION;
            pObj = new CSomeObject(pUnkOuter);
            if (pObj == NULL)
                return E_OUTOFMEMORY;
            // Set up the right unknown for delegation (the non-aggregation case)
            if (pUnkOuter == NULL)
                pObj->m_pUnkOuter = (IUnknown*)pObj ;
            HRESULT hr;
            if (FAILED(hr = pObj->QueryInterface(riid, (void**)ppv)))
                delete pObj ;
            return hr;
        }
 
        // Inner IUnknown members, non-delegating
        // Inner QueryInterface only controls inner object
        STDMETHODIMP QueryInterface(REFIID riid, void** ppv)
        {
            *ppv=NULL;
            if (riid == IID_IUnknown)
                *ppv=this;
            if (riid == IID_ISomeInterface)
                *ppv=&m_ImpSomeInterface;
            if (NULL==*ppv)
                return ResultFromScode(E_NOINTERFACE);
            ((IUnknown*)*ppv)->AddRef();
            return NOERROR;
        } ;
        STDMETHODIMP_(DWORD) AddRef(void)
        {    return ++m_cRef; };
        STDMETHODIMP_(DWORD) Release(void)
        {
            if (--m_cRef != 0)
                return m_cRef;
            delete this;
            return 0;
        };
};
 
Aggregating Objects
When developing an aggregable object, the following rules apply:

· When creating the inner object, the outer object must explicitly ask for its IUnknown.

· The outer object must protect its implementation of Release from reentrancy with an artificial reference count around its destruction code.

· The outer object must call its controlling IUnknown’s Release if it queries for a pointer to any of the inner object’s interfaces. To free this pointer, the outer object calls its controlling IUnknown’s AddRef, followed by Release on the inner object’s pointer.

// Obtaining inner object interface pointer
pUnkInner->QueryInterface(IID_ISomeInterface, &pISomeInterface);
pUnkOuter->Release();
 
// Releasing inner object interface pointer
pUnkOuter->AddRef();
pISomeInterface->Release();
 
· The outer object must not blindly delegate a query for any unrecognized interface to the inner object, unless that behavior is specifically the intention of the outer object.
<<-- end quote
0
 

Author Comment

by:hed
ID: 1180775
Adjusted points to 50
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
For most people, the WrapPanel seems like a magic when they switch from WinForms to WPF. Most of us will think that the code that is used to write a control like that would be difficult. However, most of the work is done by the WPF engine, and the W…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

732 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question