问题
I'm trying to implement a collections of objects via VC6 that can be accessed by a VB6 programs. I haven't been able to make it come together.
I have defined _CopyVariantFromAdaptItf and _CopyItfFromAdaptItf (from "ATL internals"). Here are my defines to be used in my collections definitions:
#define CComEnumVariantOnListOfItemInterface(ItemInterface) \
CComEnumOnSTL<IEnumVARIANT, &IID_IEnumVARIANT, VARIANT,_CopyVariantFromAdaptItf<ItemInterface>,vector< CAdapt< CComPtr<ItemInterface> > > >
#define ClassInterfaceCollImpl(ContainerInterface,ItemInterface) \
ICollectionOnSTLImpl< IDispatchImpl< ContainerInterface, &__uuidof(ContainerInterface) >,\
vector< CAdapt< CComPtr<ItemInterface> > >,ItemInterface*,_CopyItfFromAdaptItf<ItemInterface>,\
CComEnumVariantOnListOfItemInterface(ItemInterface) >
#define ContainerInterface IFields
#define ContainerClass CFields
#define ContainerClsid CLSID_Fields
#define ItemInterface IField
#define DllRegID IDR_FIELDS
typedef std::vector< CAdapt< CComPtr<ItemInterface> > > ContainerType;
and this the preamble for the container class:
class ATL_NO_VTABLE ContainerClass :
public ClassInterfaceCollImpl(ContainerInterface,ItemInterface),
public ISupportErrorInfo,
public CComObjectRoot,
public CComCoClass<ContainerClass,&ContainerClsid>
{
public:
ContainerClass();
BEGIN_COM_MAP(ContainerClass)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(ContainerInterface)
COM_INTERFACE_ENTRY(ISupportErrorInfo)
END_COM_MAP()
//DECLARE_NOT_AGGREGATABLE(CFields)
// Remove the comment from the line above if you don't want your object to
// support aggregation.
DECLARE_REGISTRY_RESOURCEID(DllRegID)
// ISupportsErrorInfo
STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
// IFields
private:
int GetIndex( BSTR name );
etc....
and in my attempted implementation, I'm trying to scan the included objects for a matching name that is accessed in the object's function pName(). Note that I'm showing two different approaches that I have tried:
int CFields::GetIndex( BSTR name )
{
long count = 0;
#if (1)
Count(&count);
for (unsigned int i=0; i<count; i++)
if (wcscmp( name, m_coll.m_T->pName())
return (i);
#else
std::vector<CAdapt<CComPtr<IField> > >::iterator itr;
for (itr = m_coll.begin(); itr != m_coll.end(); itr++)
if (wcscmp( name, itr->m_T->pName()))
count++;
else
return (count);
#endif
throw E_INVALIDARG_13;
}
If I try the #if (1), I get an error that m_T is not a member of "vector<...". If I try m_coll->m_T, I get an error that "vector<..." does not have overloaded ->, which I would expect. If I try the #if (0), I get an error that pName() is not a member of '_NoAddRefReleaseOnCComPtr
Thanks in advance for any help you can give me!
Vance
回答1:
I know I'm talking to myself, but I'm hoping to help someone else in case I stumble across a CORRECT answer.
Ok, I have a working system and based on the response to another question How to retrieve object pointer from ATL collection of objects?, this is what I ended up with. I added the line:
COM_INTERFACE_ENTRY_IID(CLSID_Fields, CFields)
between the BEGIN_COM_MAP(CFields) and END_COM_MAP() lines so that getItemObjectPtr would work.
I changed the ItemInterface back to IField and changed the GetIndex method to:
long count = 0;
ContainerType::iterator itr;
for (itr = m_coll.begin(); itr != m_coll.end(); itr++)
if (wcscmp( name, getItemObjectPtr( itr->m_T )->pName()) == 0)
count++;
else
return (count);
throw (HRESULT)E_INVALIDARG_13;
and the method getItemObjectPtr is defined as:
CFields * CrecordSet::getItemObjectPtr( IFields *ppFields )
{
CComQIPtr<CFields, &CLSID_Fields> pFields = ppFields;
return (pFields);
}
来源:https://stackoverflow.com/questions/16524138/in-icollectiononstlimpl-implementation-cant-access-m-t-or-item-objects-member