Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/164.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何从对象的ATL集合中检索对象指针?_C++_Com_Atl - Fatal编程技术网

C++ 如何从对象的ATL集合中检索对象指针?

C++ 如何从对象的ATL集合中检索对象指针?,c++,com,atl,C++,Com,Atl,我有一个对象集合,定义为: typedef IField ItemInterface; typedef CComObject<CField>* ItemClassPtr; typedef CAdapt< CComPtr<ItemInterface> > ItemType; typedef std::vector< ItemType > ContainerType; 现在我试图检索一个指向对象的指针,以便调

我有一个对象集合,定义为:

typedef IField                  ItemInterface;
typedef CComObject<CField>*     ItemClassPtr;
typedef CAdapt< CComPtr<ItemInterface> > ItemType;
typedef std::vector< ItemType > ContainerType;
现在我试图检索一个指向对象的指针,以便调用它的一个方法:

ItemClassPtr pField;
short type1;
m_coll[index].m_T->QueryInterface( __uuidof(ItemInterface), (void **)&pField ) );
pField->get_Type(&type1);
在get_类型调用中,如果访问冲突,它就会崩溃。 根据回复者的帖子,此内容更改为:

short type1;
IField * ppField = m_coll[index].m_T;
CComQIPtr<CField, &__uuidof(IField)> pField = ppField;
pField->get_Type(&type1);
shorttype1;
i字段*ppField=m\u coll[index].m\u T;
CComQIPtr pField=ppField;
pField->get_Type(&type1);
但当我尝试在get_类型调用中跟踪时,它仍然崩溃

以下是CField类定义的前言:

class ATL_NO_VTABLE CField : 
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CField, &CLSID_Field>,
    public ISupportErrorInfo,
    public IFieldAccess,
    public IDispatchImpl<IField, &IID_IField, &LIBID_SQLite02>
{
    friend class CFields;
    friend class CrecordSet;
public:
    CField();
    ~CField();

DECLARE_REGISTRY_RESOURCEID(IDR_FIELD)

DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(CField)
    COM_INTERFACE_ENTRY(IField)
    COM_INTERFACE_ENTRY(IDispatch)
    COM_INTERFACE_ENTRY(ISupportErrorInfo)
    COM_INTERFACE_ENTRY_IID(__uuidof(IField), CField)
END_COM_MAP()
class ATL\u NO\u VTABLE字段:
公共CComObjectRootEx,
公共课程,
公共ISupportErrorInfo,
公共访问,
公共场所
{
友人班;
朋友级录音机;
公众:
CField();
~CField();
声明\u注册表\u资源ID(IDR\u字段)
声明\u保护\u最终\u构造()
开始地图(CField)
COM_接口_条目(IField)
COM_接口_条目(IDispatch)
COM_接口_条目(ISupportErrorInfo)
COM_接口_条目_IID(uuuuIdof(IField),CField)
END_COM_MAP()
请帮忙

请注意,此问题是先前ATL问题的一个分支 这更全面地描述了集合类。我用typedefs替换了#defines


Vance

您不能使用
查询接口()
要获取指针,请仅获取接口指针。您也不能将接口指针类型转换为类指针。访问实现类的唯一安全方法是定义该类实现的单独私有接口,并让该接口公开一个返回t的方法类对象的
指针。例如:

class CField;

interface DECLSPEC_UUID("...") IFieldAccess : public IUnknown
{
public:
    virtual CField* get_ClassPtr() = 0;
};

class ATL_NO_VTABLE CField : 
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CField, &CLSID_Field>,
    public IDispatchImpl<IField, &IID_IField, &LIBID_SQLite02>,
    public ISupportErrorInfo,
    public IFieldAccess,
{
    friend class CFields;
    friend class CrecordSet;
public:
    CField();
    ~CField();

DECLARE_REGISTRY_RESOURCEID(IDR_FIELD)

DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(CField)
    COM_INTERFACE_ENTRY(IDispatch)
    COM_INTERFACE_ENTRY(IField)
    COM_INTERFACE_ENTRY(IFieldAccess)
    COM_INTERFACE_ENTRY(ISupportErrorInfo)
END_COM_MAP()
};

CField* CField::get_ClassPtr()
{
    return this;
}
类字段;
接口DECLSPEC_UUID(“…”)IFieldAccess:公共IUnknown
{
公众:
虚拟CField*get_ClassPtr()=0;
};
类别ATL_NO_VTABLE字段:
公共CComObjectRootEx,
公共课程,
公共场所,
公共ISupportErrorInfo,
公共访问,
{
友人班;
朋友级录音机;
公众:
CField();
~CField();
声明\u注册表\u资源ID(IDR\u字段)
声明\u保护\u最终\u构造()
开始地图(CField)
COM_接口_条目(IDispatch)
COM_接口_条目(IField)
COM_接口_条目(IFieldAccess)
COM_接口_条目(ISupportErrorInfo)
END_COM_MAP()
};
CField*CField::get_ClassPtr()
{
归还这个;
}

CComPtr pFieldAccess;
CField*pField;
短型1;
m_coll[index].m_T->QueryInterface(__uuidof(IFieldAccess),(void**)和pFieldAccess));
pField=pFieldAccess->get_ClassPtr();
pField->get_Type(&type1);

您使用
QueryInterface
查询
ItemInterface
/
IField
,因此您获得的指针属于这种类型(假设COM对象本身正确实现了该方法)

因此,您接下来要做的是从
IField
ItemClassPtr
/
cMobject*
的无效重新解释。这不起作用:在
pField
的行中,您的异常在那里有无效的非空指针

这里的另一个问题是引用计数过多:您的原始指针
ppField
接收到一个计数器递增的指针,我看不出您在这里释放它,我想您可能在其他地方管理引用时也出错了。如果代码中存在其他引用计数问题,您最终可能会遇到很多问题如果您的对象已经被销毁,并且您有一个指向已销毁对象的指针的调用,则代码上也会出现类似的访问冲突

此时有助于解决问题的是异常位置的调用堆栈。根据当前描述,不清楚您在
get\u Type
调用中的深度

BTW,如果您试图从接口指针恢复C++类指针,那么如果没有封送处理,很容易出现问题,否则,从<代码> iFiel**/COD>获得<代码> cFiel*>代码>,在不存在MHHSHILAN的情况下,您可以这样做:

IField* pField = ...
CField* pNativeField = static_cast<CField*>(pField);

<>这是简单的,引用计数器友好。上面的<代码> COMION接口FAX >代码创建一个伪造的接口条目,它通过“代码> QueryInterface < /CODE >一个原始C++指针公开。这将返回<代码> EyNoCuffe<代码>错误,而不崩溃。l、 我在创建例程中添加了一个ppField->Release(),这样引用计数器就正确了.m_T;CComQIPtr pField=ppField;-pField仍然指向错误的位置。我将在原始问题中添加CField类前言以及您建议的更改。我查看了您的
CField
代码,并分别更新了我的答案(最后一个代码片段),您需要将更新复制到您的代码中。指定CLSID_字段似乎可以做到这一点。我遇到了另一个问题,但至少我在get_类型例程中。谢谢!Remy的解决方案的问题是它也是一个黑客。
IFieldAccess
使用不可封送的COM类型(原始指针),所以它只在这个解决方案有效的地方工作-没有任何情况下它能以任何方式更安全地工作。更多无用的代码专用于黑客本身(你必须声明一个单独的无用类!),速度较慢,没有真正的优势。我不需要实现IFieldAccess::get_ClassPtr()
CField
类实现了
IFieldAccess
接口。
CField::get\u ClassPtr()
方法是
IFieldAccess::get\u ClassPtr()
实现。这是我的想法,但我得到了IFieldAccess::get\u ClassPtr(void)未找到链接错误。请注意,我将_接口更改为接口,并假设IFieldAccessPtr为“IFieldAccess*”。它需要在接口中声明为纯虚拟。我更新了我的answe
CComPtr<IFieldAccess> pFieldAccess;
CField* pField;
short type1;
m_coll[index].m_T->QueryInterface( __uuidof(IFieldAccess), (void **)&pFieldAccess) );
pField = pFieldAccess->get_ClassPtr();
pField->get_Type(&type1);
IField* pField = ...
CField* pNativeField = static_cast<CField*>(pField);
CComPtr<IField> pField = ...
CField* pNativeField = static_cast<CField*>((IField*) pField);
// NOTE: pNativeField is valid until at least pField is released
class ATL_NO_VTABLE CField :
// ...
BEGIN_COM_MAP(CField)
  //...
  COM_INTERFACE_ENTRY_IID(CLSID_Field, CField)
END_COM_MAP( )

//...

IField* pField = ...
CComQIPtr<CField, &CLSID_Field> pNativeField = pField;