有关QueryInterface的菜鸟问题

kukafei 2002-03-26 05:26:21
我定义了基于IDispatch的IParam和IWork
在IWork 的GetDetails([out] IParam **pVal)中
STDMETHODIMP CWork::GetDetail(IParam **pVal)
{
HRESULT hr = S_OK;
IParam *pParam = NULL;
hr = QueryInterface(__uuidof(IParam) , (void **)&pParam);
if(FAILED(hr))
{
AfxMessageBox("no ok");
// return hr;
}
return S_OK;
}
为什么QueryInterface后总不成功, if(FAILED(hr))总为真
...全文
140 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
walterzh 2002-05-03
  • 打赏
  • 举报
回复
这个老帖子很好,翻出来和大家共享。

最后comxp(Com的初体验) 说的很好
如果要在不同的Com对象中分别实现这两个接口
则在CWork的定义中加上IParam *m_param
而在GetDetail中*pVal = m_param,简单的返回子对象指针就可以
不知可对?
ComXP 2002-03-29
  • 打赏
  • 举报
回复
你的Param和Work是分别实现了IParam和IWork的两个对象,在Work对象中怎么可能查得到IParam接口呢?QueryInterface失败是当然的。如果你的对象是
coclass CWork
{
[default] interface IWork;
interface IParam;
}
你的QueryInterface才能成功。如果你要在不同的Com对象中分别实现这两个接口,那你只能在GetDetail中创建一个CParam对象了。
四大皆空相 2002-03-29
  • 打赏
  • 举报
回复
哦, 考虑了一下, 有这么一个可能:

NUM()是一个重载函数, 而get_NUM()和put_NUM()

本质就是NUM(),一个是NUM()的in函数,另一个是out函数,

而IDL在设计时人为的为重载函数加入get_、put_前缀,

而后在编译时再去掉,这样,分发ID依旧是一个,NUM()函数

也依旧是一个。 这种推断不知是否正确。望大虾们继续探讨。
Erlin 2002-03-29
  • 打赏
  • 举报
回复
其实在IDispath接口看来,是一个属性,对于同一个ID,IDispatch 在 Invoke的时候会有不同的方式:
DISPATCH_METHOD
DISPATCH_PROPERTYGET
DISPATCH_PROPERTYPUT
DISPATCH_PROPERTYPUTREF

而当我们不使用IDispath接口,而使用虚表的时候,它就是两个方法,我怀疑这样做的目的是为了避免[in,out]参数。


四大皆空相 2002-03-29
  • 打赏
  • 举报
回复
多谢,

可是问题明显了:

interface IParam : IDispatch
{
[propget, id(1), helpstring("property Num")] HRESULT Num([out, retval] long *pVal);
[propput, id(1), helpstring("property Num")] HRESULT Num([in] long newVal);
};

声明的是 "一个" NUM() 一个id, 却蹦出两个函数 get_NUM(),put_NUM(),

如此,分发id如何处置? 客户端调用NUM() 又如何绕道get_NUM() put_NUM()?

后者这两个函数在接口声明中根本没有出现. 非常迷惑!!!
LLnju 2002-03-29
  • 打赏
  • 举报
回复
头文件对应:
/*object,uuid(),dual,helpstring.....*/
interface IParam : public IDispatch
{
/*id,propput,helpstring*/STDMETHOD(put_Num)( /*in*/long newVal ) PURE;
/*id,propget,helpstring*/STDMETHOD(get_Num( /*out,retval*/long* pVal ) PURE;
};
四大皆空相 2002-03-28
  • 打赏
  • 举报
回复
to:kukafei()

看了一下你的代码,说一下自己的看法,不托之处,望指正.

先说一下,我还没用过atl,所以对你idl产生一点疑惑:

用idl描述的IParam接口仅有一个函数:Num,是输入输出函数,

但我看到,在.h文件中出现了两个函数:get_Num,put_Num,

按道理来说,仅有一个分发id,不会这样啊.Atl惹的祸?

第二点是:在代码中,你确实实现了两个组件对象.这对你的

QueryInterface()来说是个灾难. 因为在CWork中,你没有

实现自己的QueryInterface().

如果你想解决这个问题,最简单的方法是:并为一个对象.并且

也省掉了QueryInterface()实现的烦恼.

Other way:把前者(CParam)做成可聚合组件,也就是说将出现:

param.dll,work.dll,CWork为聚合体,这样也可以调用IParam接口.

大体的实现方式,同我上面讲的相似.但要实现QueryInterface(),

而且在CParam中要实现两边:委托,非委托.哦,可能Atl帮你做一些,

我不清楚哟,但在Atl中查一下聚合,就有大案了.

是不是还有第三种方式,大家讨论拉.

第三:

for(int i=0;i<5;i++)
{

hr=QueryInterface(__uuidof(IWork), (void **)&q[i]);
~~~~
//注意if判断.
q[i]->SetI(i);
}
return S_OK;

另:是否可以:


hr=QueryInterface(__uuidof(IWork), (void **)&q);

for(int i=0;i<5;i++)
{
q->SetI(i);
}

这样可以避免引用记数的烦恼啊.


四大皆空相 2002-03-28
  • 打赏
  • 举报
回复

>>这没有毛病,对象的属性当然是这样定义和实现的。

interface IParam : IDispatch
{
[propget, id(1), helpstring("property Num")] HRESULT Num([out, retval] long *pVal);
[propput, id(1), helpstring("property Num")] HRESULT Num([in] long newVal);
};

我有些糊涂:Num()应是一个重载函数,实现的是输入输出,

我想.h文件的声明对应的接口声明应该与下面等价:

interface IParam : IDispatch
{
[id(0)] HRESULT get_Num([out, retval] long *pVal);
[id(1)] HRESULT put_Num([in] long newVal);
};

不知对否? 请指点.
LLnju 2002-03-28
  • 打赏
  • 举报
回复
STDMETHODIMP CWork::GetParams(IParam **pVal)
{
..........
hr = QueryInterface(__uuidof(IParam),(void **)&pParam);
..........
}
有毛病, CWork 没有实现 IParam 接口,当然 QI失败,另外,看不懂你是怎么样实现的,好像毛病颇多。

>>我发现循环到最后一次,即第5次时的IWork就将以前的指针覆盖了,即q[5]的指针和q[1]的是一样的
当然如此,他们本身就是一个对象,不返回相同的指针还返回什么。记住 QI 返回的是和自己同一个对象,也就是 A->QI( IUnknown ) == A->QI( IB )->QI( IUnknown )

to fanchka(狼仔):
>>用idl描述的IParam接口仅有一个函数:Num,是输入输出函数
>>但我看到,在.h文件中出现了两个函数:get_Num,put_Num
这没有毛病,对象的属性当然是这样定义和实现的。

>>实现自己的QueryInterface().
这些事情 ATL 已经帮你做了,没有必要,并且你写了就是错的。

to kukafei ():
把你的程序的功能,用法贴出来,好像你贴的程序颇为混乱,实在不好改,应该是设计上有问题。
四大皆空相 2002-03-27
  • 打赏
  • 举报
回复
有种方式,类似于前置声明.

比如本例中,先声明一个IParam接口(里面的函数

声明与本例的IParam完全一致,且为纯虚拟),而后CWork继承.

再,在QureryInterface()中,加入IParam的查询即可.

在跨进程中有这种实现方式.

共同讨论.
arxing 2002-03-27
  • 打赏
  • 举报
回复
QueryInterface只能用于同一个对象之间不同的接口之间的查询。
四大皆空相 2002-03-27
  • 打赏
  • 举报
回复

我想问题应该在QureyInterface()的实现中.

你可能实现了两个组件对象,

如此一来,CWork::QureyInterface()的实现应是焦点.

你可以贴上来.
kukafei 2002-03-27
  • 打赏
  • 举报
回复
补充
还有一个问题也有点怪
STDMETHODIMP CWork::GetDetails(ITxList **pVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())

// TODO: Add your implementation code here
IWork *q[5];
for(int i=0;i<5;i++)
{

QueryInterface(__uuidof(IWork), (void **)&q[i]);
q[i]->SetI(i);
}
return S_OK;
}
我发现循环到最后一次,即第5次时的IWork就将以前的指针覆盖了,即q[5]的
指针和q[1]的是一样的
将QueryInterface改成CoCreateInstance就对了
kukafei 2002-03-27
  • 打赏
  • 举报
回复
我的idl
MyWork.idl
import "oaidl.idl";
import "ocidl.idl";
[
object,
uuid(52D924C0-67AF-4321-83AA-29BC4212BC00),
dual,
helpstring("IParam Interface"),
pointer_default(unique)
]
interface IParam : IDispatch
{
[propget, id(1), helpstring("property Num")] HRESULT Num([out, retval] long *pVal);
[propput, id(1), helpstring("property Num")] HRESULT Num([in] long newVal);
};
[
object,
uuid(8C7DC75A-E9E1-4EA5-B5DC-0AD4F5F81285),
dual,
helpstring("IWork Interface"),
pointer_default(unique)
]
interface IWork : IDispatch
{
[id(1), helpstring("method GetParams")] HRESULT GetParams([out] IParam **pVal);
};

[
uuid(96F377CE-371A-49E6-A71D-60C9B16568BB),
version(1.0),
helpstring("MyWork 1.0 Type Library")
]
library MYWORKLib
{
importlib("stdole32.tlb");
importlib("stdole2.tlb");

[
uuid(2EB76ABA-0355-41CC-BED2-436E9C4D7F61),
helpstring("Param Class")
]
coclass Param
{
[default] interface IParam;
};
[
uuid(B233267F-0F78-4F45-9B20-6DCEB7AECC2C),
helpstring("Work Class")
]
coclass Work
{
[default] interface IWork;
};
};


我的Param.h
// Param.h : Declaration of the CParam

#ifndef __PARAM_H_
#define __PARAM_H_

#include "resource.h" // main symbols

/////////////////////////////////////////////////////////////////////////////
// CParam
class ATL_NO_VTABLE CParam :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CParam, &CLSID_Param>,
public IDispatchImpl<IParam, &IID_IParam, &LIBID_MYWORKLib>
{
public:
CParam()
{
}

DECLARE_REGISTRY_RESOURCEID(IDR_PARAM)

DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(CParam)
COM_INTERFACE_ENTRY(IParam)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()

// IParam
public:
int m_Num;
STDMETHOD(get_Num)(/*[out, retval]*/ long *pVal);
STDMETHOD(put_Num)(/*[in]*/ long newVal);
};

#endif //__PARAM_H_

我的Param.cpp

// Param.cpp : Implementation of CParam
#include "stdafx.h"
#include "MyWork.h"
#include "Param.h"

/////////////////////////////////////////////////////////////////////////////
// CParam


STDMETHODIMP CParam::get_Num(long *pVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())

// TODO: Add your implementation code here
*pVal = m_Num;
return S_OK;
}

STDMETHODIMP CParam::put_Num(long newVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())

// TODO: Add your implementation code here
m_Num = newVal;
return S_OK;
}
我的CWork.h

// Work.h : Declaration of the CWork

#ifndef __WORK_H_
#define __WORK_H_

#include "resource.h" // main symbols

/////////////////////////////////////////////////////////////////////////////
// CWork
class ATL_NO_VTABLE CWork :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CWork, &CLSID_Work>,
public IDispatchImpl<IWork, &IID_IWork, &LIBID_MYWORKLib>
{
public:
CWork()
{
pParam = NULL;
}

DECLARE_REGISTRY_RESOURCEID(IDR_WORK)

DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(CWork)
COM_INTERFACE_ENTRY(IWork)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()

// IWork
public:
STDMETHOD(GetParams)(/*[out]*/ IParam **pVal);
IParam * pParam;
};

#endif //__WORK_H_

我的CWork.cpp
// Work.cpp : Implementation of CWork
#include "stdafx.h"
#include "MyWork.h"
#include "Work.h"

/////////////////////////////////////////////////////////////////////////////
// CWork


STDMETHODIMP CWork::GetParams(IParam **pVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())

// TODO: Add your implementation code here
HRESULT hr = S_OK;
hr = QueryInterface(__uuidof(IParam),(void **)&pParam);
if(SUCCEEDED(hr))
{
AfxMessageBox("ok");
pParam->put_Num(5);
}
AfxMessageBox("not ok");
*pVal = pParam;
return S_OK;
}
这是我的全部代码
但QueryInterface总不成功
kukafei 2002-03-26
  • 打赏
  • 举报
回复
有一个CParam实现IParam
kukafei 2002-03-26
  • 打赏
  • 举报
回复
说错了,CWork实现IWork
kukafei 2002-03-26
  • 打赏
  • 举报
回复
也是
unkill 2002-03-26
  • 打赏
  • 举报
回复
你的IParam的实现类也是CWork吗?
kukafei 2002-03-26
  • 打赏
  • 举报
回复
我是要将IParam传出来
STDMETHODIMP CWork::GetDetail(IParam **pVal)
{
HRESULT hr = S_OK;
IParam *pParam = NULL;
hr = QueryInterface(__uuidof(IParam) , (void **)&pParam);
if(FAILED(hr))
{
AfxMessageBox("no ok");
// return hr;
}
pParam->SetNum(8);
*pVal = pParam;
return S_OK;
}
但是QueryInterface出错了
kukafei 2002-03-26
  • 打赏
  • 举报
回复
说清楚点,我是要将IParam 传出来,最终要赋给*pVal
STDMETHODIMP CWork::GetDetail(IParam **pVal)
{
HRESULT hr = S_OK;
IParam *pParam = NULL;
hr = this->QueryInterface(__uuidof(IParam) , (void **)&pParam);
pParam -> SetNum(5);
if(FAILED(hr))
{
AfxMessageBox("no ok");
// return hr;
}
pParam -> SetNum(5);
*pVal = pParam;
return S_OK;
}

可是QueryInterface却出错了
加载更多回复(1)

1,649

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 非技术类
社区管理员
  • 非技术类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧