Solved

ATL collection copy class

Posted on 2002-05-10
7
434 Views
Last Modified: 2013-12-14
Hi all

I am using ATL collections.  I don't really how they work but I am using the following code in my collection header file

// IRestrictedSystemKey specific enumerator
typedef CComEnumOnSTL<IEnumVARIANT,        // class Base
          &IID_IEnumVARIANT,                  // const IID* piid
          VARIANT,                                                                                          // class T
          _CopyVariantFromAdaptItf<ICN10RestrictedSystemKey>,     // class Copy
          std::list< CAdapt< CComPtr<ICN10RestrictedSystemKey> > > >     // class CollType
          CComEnumVariantOnListOfSystemKeys;

// IRestrictedSystemKey specific collection methods
typedef ICollectionOnSTLImpl<IDispatchImpl<ICN10RestrictedSystemKeys, &IID_ICN10RestrictedSystemKeys>,     // class T
          std::list< CAdapt< CComPtr<ICN10RestrictedSystemKey> > >,          // class CollType
          ICN10RestrictedSystemKey*,                                                  // class ItemType
          _CopyItfFromAdaptItf<ICN10RestrictedSystemKey>,                    // class CopyItem
         CComEnumVariantOnListOfSystemKeys>                         // class EnumType
          IRestrictedSystemKeyCollImpl;

/////////////////////////////////////////////////////////////////////////////
// CCN10RestrictedSystemKeys
class ATL_NO_VTABLE CCN10RestrictedSystemKeys :
     public CComObjectRootEx<CComSingleThreadModel>,
     public CComCoClass<CCN10RestrictedSystemKeys, &CLSID_CN10RestrictedSystemKeys>,
     public ISupportErrorInfo,
     public IRestrictedSystemKeyCollImpl



I also have another class that acts as a copy policy class which looks like this

// atlstlVarItfCollection.h

#ifndef _atlstlVarItfCollection_h_
#define _atlstlVarItfCollection_h_

// GJPJ 30/4/2002 - taken from ATL Internals

// reusable class that converts an interface into a VARIANT
// for use in enumerating a collection of interface pointers
template <typename T>
struct _CopyVariantFromAdaptItf
{
     static HRESULT copy(VARIANT* p1, CAdapt< CComPtr<T> >* p2)
     {
          HRESULT hr = p2->m_T->QueryInterface(IID_IDispatch, (void**)&p1->pdispVal);
          if (SUCCEEDED(hr))
               p1->vt = VT_DISPATCH;
          else
          {
               hr = p2->m_T->QueryInterface(IID_IUnknown, (void**)&p1->punkVal);
               if (SUCCEEDED(hr))
                    p1->vt = VT_UNKNOWN;
          }

          return hr;
     }

     static void init(VARIANT* p) { VariantInit(p); }
     static void destroy(VARIANT* p) { VariantClear(p); }
};

// reusable class that implements the Item property assuming
// an STL container holding elements of type CAdapt<CComPtr<T>>
template <typename T>
struct _CopyItfFromAdaptItf
{
     static HRESULT copy(T** p1, CAdapt< CComPtr<T> >* p2)
     {
          if (*p1 = p2->m_T) return (*p1)->AddRef(), S_OK;
          return E_POINTER;
     }

     static void init(T** p) {}
     static void destroy(T** p) { if (*p) (*p)->Release(); }
};

#endif




My problem is that when I access the Item property through the get_Item method it calls the copy policy class method copy() which I think is correct but the returned item is garbage and its  private members are empty although I know I put values into them

Could someone have a look at this copy class and tell me what it is doing? and hopefully get a fix my problem.  The items in the collection are are ATL simple objects created with dual interface optoin.  There is a 3 protected member variables of type _bstr_t and their get and put properties.

Thanks in advance
Cheers
Hassan

 
0
Comment
Question by:gbzhhu
[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
  • 3
  • 2
  • 2
7 Comments
 
LVL 49

Expert Comment

by:DanRollins
ID: 7004765
What is the return from the copy() fn.  What happens when you single-step into the copy() fn?  It looks rather odd, what with that comma before S_OK.

-- Dan
0
 
LVL 22

Accepted Solution

by:
ambience earned 300 total points
ID: 7005187
Have you tried debug , apparently i could not find anything wrong with this code.

Try the following code , and if it works then perhaps there is a problem with using CCOmPtr with stl containers, however i dont think there should be any. In other cases try to watch the calls into copy() and see if you can find out the place where garbage creeps into.

typedef std::vector< IObject* > ColType;

template<class T>
class CopyObject : public _Copy<VARIANT>
{
public:
     static HRESULT copy(VARIANT* p1,T * p2)
     {
          p1->vt = VT_DISPATCH;
          p1->pdispVal = *p2;
          (*p2)->AddRef();
          return S_OK;
     }
};

typedef CComEnumOnSTL< IEnumVARIANT,
                            &__uuidof(IEnumVARIANT),
                            VARIANT,
                            CopyObject<ColType::value_type>,
                            ColType> EnumeratorType;

typedef ICollectionOnSTLImpl<IObjects,
                                    ColType,
                                    ColType::value_type,
                                    _CopyInterface<IObject>,
                                    EnumeratorType >    CollectionType;


class ATL_NO_VTABLE CObjects :
     public CComObjectRootEx<CComSingleThreadModel>,
     public CComCoClass<CObjects, &CLSID_Objects>,
     public IDispatchImpl<CollectionType, &IID_IObjects, &LIBID_ATLTESTLib>

replacce IObject by ICN10xxxxxxxxxxx etc.

DanRollins:
, is the usual sequqnce operator.
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 7005413
>>, is the usual sequqnce operator.

So the command:

    return void,S_OK;

is a reasonable construct?  Even if it works, it seens unnecessarily obfuscated to me.  I see that your code uses a straightforward:

   (*p2)->AddRef();
   return S_OK;

-- Dan
0
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!

 
LVL 22

Expert Comment

by:ambience
ID: 7005511
>>  return void,S_OK;
>> is a reasonable construct?  Even if it works, it seens unnecessarily obfuscated to me.

yes it is a *valid* construct (if void means an expression that result into a void value), obfuscated perhaps, its intended to be used for situation where only a single statement is allowed (though you can always break it up into multiple statements), but this is an allowed construct.

a good example can be

a=0, b=1, c=2, d=4;
0
 
LVL 12

Author Comment

by:gbzhhu
ID: 7005541
Hi Da and Ambience

Ambience was right, there was nothing wrong with the code.  I found the problem, it was my stupidity.  The point where I was adding an item in the collection, I was creating a new item and adding it to the collection ignoring the one passed as a parameter.  This was because it waa a copy and paste code and I forgot to modify.

Thanks for you input.  I think you both deserve the points so I will split it between you.  How do I go about this?

Hassan

0
 
LVL 49

Expert Comment

by:DanRollins
ID: 7005591
I don't feel like I deserved any points here.  Please award to ambience.  Thanks for the offer tho!

-- Dan
0
 
LVL 12

Author Comment

by:gbzhhu
ID: 7005706
Ambience

Thanks for your effort

Hassan
0

Featured Post

Enroll in June's Course of the Month

June’s Course of the Month is now available! Experts Exchange’s Premium Members, Team Accounts, and Qualified Experts have access to a complimentary course each month as part of their membership—an extra way to sharpen your skills and increase training.

Question has a verified solution.

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

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The viewer will learn how to use NetBeans IDE 8.0 for Windows to connect to a MySQL database. Open Services Panel: Create a new connection using New Connection Wizard: Create a test database called eetutorial: Create a new test tabel called ee…
The viewer will learn how to synchronize PHP projects with a remote server in NetBeans IDE 8.0 for Windows.

696 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