如何将 SAFEARRAY 转换为 COM 指针数组
How to convert a SAFEARRAY to array of COM pointers
我有一个函数说 foo
其中 returns COM 指针的 SAFEARRAY
SAFEARRAY* foo()
{
IMyClassPtr *objs = (IMyClassPtr*)callock(n, sizeof(IMyClassPtr));
CComSafeArray<IDispatch*> sa(n);
for(UINT index = 0; index < n; index++)
{
objs[index].CreateInstance(CLSID_MyClass);
(objs[index])->AddRef();
objs[index]->put_X(index);
objs[index]->put_Y(index+10);
sa.SetAt(index, objs[index]);
}
return sa.Detach();
}
这是我的MyClass
class ATL_NO_VTABLE CMyClass :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CMyClass, &CLSID_MyClass>,
public IDispatchImpl<IMyClass, &IID_IMyClass, &LIBID_mylibAlias, /*wMajor =*/ 1, /*wMinor =*/ 0>
{
public:
CMyClass();
virtual ~CMyClass();
DECLARE_REGISTRY_RESOURCEID(IDR_MyClass)
BEGIN_COM_MAP(CMyClass)
COM_INTERFACE_ENTRY(IMyClass)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
protected:
ULONG x;
ULONG y;
public:
STDMETHOD(get_X)(ULONG* pVal);
STDMETHOD(put_X)(ULONG newVal);
STDMETHOD(get_Y)(ULONG* pVal);
STDMETHOD(put_Y)(ULONG newVal);
};
OBJECT_ENTRY_AUTO(__uuidof(MyClass), CMyClass)
现在我已经做到了,
SAFEARRAY* sa;
IMyClassPtr* objs;
sa = foo();
if(SUCCEEDED(SafeArrayAccessData(sa, (void**)&objs)))
{
// At this point, when I debug at the autos window objs contains some value
// and I can see this message also
// <No type information available in symbol file for oleaut32.dll>
}
请帮我解决这个问题。
如果您的安全数组包含 IDisptach*,您调用 SafeArrayAccessDate returns IDispatch**。事实上你得到了第一个指针数组的开始。
此外,您编写创建对象的代码也不是很有用。你不需要创建对象数组(即使有泄漏你也不会再次释放它。
只需一次创建一个对象并将其分配给安全数组。不需要第二个指针。您的引用计数也有问题。据我所知,创建实例后无需调用 AddRef。是已经被锁定了。而且您不想要第二把锁。
此外,您应该始终使用 QueryInterface 来获取要存储的给定类型的指针 (IDisptach),并且当您想要将 IDispatch 转换回 IMyClass 指针时,您需要再次调用 QueryInterface。
我有一个函数说 foo
其中 returns COM 指针的 SAFEARRAY
SAFEARRAY* foo()
{
IMyClassPtr *objs = (IMyClassPtr*)callock(n, sizeof(IMyClassPtr));
CComSafeArray<IDispatch*> sa(n);
for(UINT index = 0; index < n; index++)
{
objs[index].CreateInstance(CLSID_MyClass);
(objs[index])->AddRef();
objs[index]->put_X(index);
objs[index]->put_Y(index+10);
sa.SetAt(index, objs[index]);
}
return sa.Detach();
}
这是我的MyClass
class ATL_NO_VTABLE CMyClass :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CMyClass, &CLSID_MyClass>,
public IDispatchImpl<IMyClass, &IID_IMyClass, &LIBID_mylibAlias, /*wMajor =*/ 1, /*wMinor =*/ 0>
{
public:
CMyClass();
virtual ~CMyClass();
DECLARE_REGISTRY_RESOURCEID(IDR_MyClass)
BEGIN_COM_MAP(CMyClass)
COM_INTERFACE_ENTRY(IMyClass)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
protected:
ULONG x;
ULONG y;
public:
STDMETHOD(get_X)(ULONG* pVal);
STDMETHOD(put_X)(ULONG newVal);
STDMETHOD(get_Y)(ULONG* pVal);
STDMETHOD(put_Y)(ULONG newVal);
};
OBJECT_ENTRY_AUTO(__uuidof(MyClass), CMyClass)
现在我已经做到了,
SAFEARRAY* sa;
IMyClassPtr* objs;
sa = foo();
if(SUCCEEDED(SafeArrayAccessData(sa, (void**)&objs)))
{
// At this point, when I debug at the autos window objs contains some value
// and I can see this message also
// <No type information available in symbol file for oleaut32.dll>
}
请帮我解决这个问题。
如果您的安全数组包含 IDisptach*,您调用 SafeArrayAccessDate returns IDispatch**。事实上你得到了第一个指针数组的开始。
此外,您编写创建对象的代码也不是很有用。你不需要创建对象数组(即使有泄漏你也不会再次释放它。
只需一次创建一个对象并将其分配给安全数组。不需要第二个指针。您的引用计数也有问题。据我所知,创建实例后无需调用 AddRef。是已经被锁定了。而且您不想要第二把锁。
此外,您应该始终使用 QueryInterface 来获取要存储的给定类型的指针 (IDisptach),并且当您想要将 IDispatch 转换回 IMyClass 指针时,您需要再次调用 QueryInterface。