从COM库传递对COM接口的引用
如何从COM库中将对COM接口的引用作为参数传递 以下是示例: 1) 客户端代码成功创建了coclass,并在pFunctionDiscovery中接收接口指针,如下所示:从COM库传递对COM接口的引用,com,Com,如何从COM库中将对COM接口的引用作为参数传递 以下是示例: 1) 客户端代码成功创建了coclass,并在pFunctionDiscovery中接收接口指针,如下所示: hr = CoCreateInstance( __uuidof(FunctionDiscovery), NULL, CLSCTX_INPROC_SERVER, __uuidof(IFunctionDiscovery), (LPVOID*)&
hr = CoCreateInstance(
__uuidof(FunctionDiscovery),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IFunctionDiscovery),
(LPVOID*)&pFunctionDiscovery );
if (FAILED(hr))
{
TRACE_MESSAGE(Error,"Failed to get IFunctionDiscovery COM %08x\n",hr);
goto Exit;
}
// The module attribute is specified in order to implement DllMain,
// DllRegisterServer and DllUnregisterServer
[ module(dll, name = "MyServer", helpstring = "MyServer 1.0 Type Library") ];
[ emitidl ];
/////////////////////////////////////////////////////////////////////////////
// IFunctionInstanceCollection interface
[
object,
uuid("F0A3D895-855C-42A2-948D-2F97D450ECB1"),
oleautomation,
helpstring("IFunctionInstanceCollection Interface"),
pointer_default(unique)
]
__interface IFunctionInstanceCollection : IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE GetCount(__RPC__out DWORD *pdwCount) = 0;
};
// IFunctionDiscovery interface
[
object,
uuid("4df99b70-e148-4432-b004-4c9eeb535a5e"),\
oleautomation,
helpstring("IFunctionDiscovery Interface"),
pointer_default(unique)
]
__interface IFunctionDiscovery : IUnknown
{
virtual HRESULT GetInstanceCollection(
__RPC__in_string const WCHAR* functionCategory,
__RPC__in_opt_string const WCHAR* subcategory,
BOOL fIncludeAllSubCategories,
__RPC__deref_out_opt IFunctionInstanceCollection **ppIFunctionInstanceCollection
) = 0;
};
/////////////////////////////////////////////////////////////////////////////
// FunctionDiscovery class
[
coclass,
threading(apartment),
vi_progid("FunctionDiscovery.Discovery"),
progid("FunctionDiscovery.Discovery.1"),
version(1.0),
uuid("C72BE2EC-8E90-452c-B29A-AB8FF1C071FC"),
helpstring("FunctionDiscovery Class")
]
class ATL_NO_VTABLE FunctionDiscovery :
public IFunctionDiscovery
{
public:
FunctionDiscovery() {};
virtual ~FunctionDiscovery(){};
virtual HRESULT GetInstanceCollection(
__RPC__in_string const WCHAR* functionCategory,
__RPC__in_opt_string const WCHAR* subcategory,
BOOL fIncludeAllSubCategories,
__RPC__deref_out_opt IFunctionInstanceCollection **ppIFunctionInstanceCollection
)
{
printf("GetInstanceCollection called");
return 0;
}
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
static BOOL DllMainAttach();
static void DllMainDetach();
};
2) 现在,如下调用pFunctionDiscovery的成员函数会给出错误消息:800706f4,它对应于传递给存根的空引用指针
hr = pFunctionDiscovery->GetInstanceCollection(
FCTN_CATEGORY_DEVICEDISPLAYOBJECTS,
NULL,
FALSE,
&pFICollection );
3) COM库是借助ATL库编写的,代码如下:
hr = CoCreateInstance(
__uuidof(FunctionDiscovery),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IFunctionDiscovery),
(LPVOID*)&pFunctionDiscovery );
if (FAILED(hr))
{
TRACE_MESSAGE(Error,"Failed to get IFunctionDiscovery COM %08x\n",hr);
goto Exit;
}
// The module attribute is specified in order to implement DllMain,
// DllRegisterServer and DllUnregisterServer
[ module(dll, name = "MyServer", helpstring = "MyServer 1.0 Type Library") ];
[ emitidl ];
/////////////////////////////////////////////////////////////////////////////
// IFunctionInstanceCollection interface
[
object,
uuid("F0A3D895-855C-42A2-948D-2F97D450ECB1"),
oleautomation,
helpstring("IFunctionInstanceCollection Interface"),
pointer_default(unique)
]
__interface IFunctionInstanceCollection : IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE GetCount(__RPC__out DWORD *pdwCount) = 0;
};
// IFunctionDiscovery interface
[
object,
uuid("4df99b70-e148-4432-b004-4c9eeb535a5e"),\
oleautomation,
helpstring("IFunctionDiscovery Interface"),
pointer_default(unique)
]
__interface IFunctionDiscovery : IUnknown
{
virtual HRESULT GetInstanceCollection(
__RPC__in_string const WCHAR* functionCategory,
__RPC__in_opt_string const WCHAR* subcategory,
BOOL fIncludeAllSubCategories,
__RPC__deref_out_opt IFunctionInstanceCollection **ppIFunctionInstanceCollection
) = 0;
};
/////////////////////////////////////////////////////////////////////////////
// FunctionDiscovery class
[
coclass,
threading(apartment),
vi_progid("FunctionDiscovery.Discovery"),
progid("FunctionDiscovery.Discovery.1"),
version(1.0),
uuid("C72BE2EC-8E90-452c-B29A-AB8FF1C071FC"),
helpstring("FunctionDiscovery Class")
]
class ATL_NO_VTABLE FunctionDiscovery :
public IFunctionDiscovery
{
public:
FunctionDiscovery() {};
virtual ~FunctionDiscovery(){};
virtual HRESULT GetInstanceCollection(
__RPC__in_string const WCHAR* functionCategory,
__RPC__in_opt_string const WCHAR* subcategory,
BOOL fIncludeAllSubCategories,
__RPC__deref_out_opt IFunctionInstanceCollection **ppIFunctionInstanceCollection
)
{
printf("GetInstanceCollection called");
return 0;
}
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
static BOOL DllMainAttach();
static void DllMainDetach();
};
请告诉我问题出在哪里
谢谢
尼克
好的,在客户端的调用中传递一个非空字符串,效果很好。我将对象分配给*ppIFunctionInstanceCollection的方式如下:
在服务器端,我声明了一个像这样的新类,并从GetInstanceCollection中创建了一个对象。当客户端调用GetInstanceCOllection时,将返回此创建的对象。我确实在服务器端获得了一个有效实例,但在客户端,它显示为NULL
(一)
2) 在GetInstanceCollection中,我正在执行以下操作:
*ppIFunctionInstanceCollection=new CFunctionInstanceCollection()代码>
我希望上面的赋值将CFunctionInstanceCollection的有效实例转换为GetInstanceCollection()方法的最后一个参数,即*ppIFunctionInstanceCollection。我已经在服务器端验证了这一点,它打印了有效的指针,类的大小为4(存在虚拟函数时,类的大小为4)
但在客户端,值为NULL。我认为在客户机/服务器之间传递参数有更多的好处。如果你还看到什么,也请告诉我。谢谢 这就解释了为什么会出现这个问题,默认指针(unique)并不像您认为的那样。将subcategory参数指定为[unique]。如果我告诉您您已经知道的事情,请道歉
在RPC(和COM)中,a是客户端在调用远程过程时实际调用的代码段。代理通常会封送输入参数,然后将请求发送到服务器,在服务器上,一段称为“解组”的代码会对参数进行解组,然后使用它们调用正在调用的实际过程
当被调用的过程返回结果时,存根封送out参数和结果,并将响应发送回代理,代理将依次解组out参数等,并将它们交回客户端
不管怎样,这是一般模型,有时会进行优化(例如,在进程内COM对象的情况下),在这种情况下,可能没有实际的存根和实际的代理。不过,这就是我们可以用来理解什么是“代理”和“存根”的背景
“将空引用指针传递到存根”错误表明问题发生在存根(即服务器)端。可能会将内容传递给存根的两段代码是代理和GetInstanceCollection的实现,其中GetInstanceCollection更可能是罪魁祸首
我怀疑您的问题在于GetInstanceCollection实现没有为*ppIFunctionInstanceCollection赋值
在GetInstanceCollection返回之前,尝试添加代码以分配*ppIFunctionInstanceCollection
2015年3月更新
更新后的GetCount实现返回值10。但是,这将被解释为HRESULT 10,而不是计数值10。GetCount的实现应该是这样的
virtual HRESULT STDMETHODCALLTYPE GetCount(__RPC__out DWORD *pdwCount)
{
*pdwCount = 10;
return S_OK;
};
也就是说,虚构IUnknown方法(QueryInterface、AddRef和Release)并不是一个好主意,因为您可能会意外地破坏各种各样的东西。例如,每次调用GetInstanceCollection时,您的程序都会泄漏一个CfFunctionInstanceCollection实例,因为其中一个实例已创建且从未销毁
您拥有的代码可以作为一个实验,但最好使用ATL为CfFunctionInstanceCollection完全实现IUnknown,就像您为FunctionDiscovery类所做的那样
2016年3月更新
为了完整起见,我可能还应该提到,以您这样的方式分配*ppIFunctionInstanceCollection是有效的,但总体上可能存在风险
您已经编写了CFunctionInstanceCollection类,因此您知道它直接实现了IFunctionInstanceCollection接口,因此您知道您的分配是安全的。但是在没有编写类的更一般的情况下,CFunctionInstanceCollection类可能会做一些不那么直接的事情——例如,它可能会聚合实现接口的其他类。为了真正安全,您应该使用QueryInterface检索IFunctionInstanceCollection接口指针。非常感谢您编辑代码!我对COM和这个团队都是新手。我现在知道发布代码格式了。感谢您对代理/存根的介绍。这是我的怀疑,我试图通过创建来解决问题我意识到了这个问题,但是你能告诉我如何将接口指针传递到“GetInstanceCollection”吗我在C++中使用ATL库和COM服务器编码。无法创建接口的实例。那么,我应该如何将指向有效实例的指针作为COM客户端调用的GetInstanceCollection的最后一个参数来传递呢?谢谢-NickWe在这里可能会对术语感到困惑,但是客户端不应该将指向有效实例的指针作为GetInstanceCollection的最后一个参数传递。从函数名和参数定义来看,我认为GetInstanceCollection函数旨在返回指向最后一个参数中有效实例的指针。如果合适,服务器端可以通过调用CoCreateInstance来创建IFunctionInstanceCollection的实例,或者可以调用其他创建实例的函数(这是客户端通过调用GetInsta所做的)