gpt4 book ai didi

com - 从 COM 库传递对 COM 接口(interface)的引用

转载 作者:行者123 更新时间:2023-12-04 06:32:00 29 4
gpt4 key购买 nike

如何将 COM 接口(interface)的引用作为 COM 库中的参数传递?

这是示例:

1)客户端代码成功创建coclass并接收到pFunctionDiscovery中的接口(interface)指针如下:

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;
}

2) 现在调用 pFunctionDiscovery 的成员函数如下给出错误消息:800706f4,对应于将空引用指针传递给 stub 。
hr = pFunctionDiscovery->GetInstanceCollection(
FCTN_CATEGORY_DEVICEDISPLAYOBJECTS,
NULL,
FALSE,
&pFICollection );

3)COM库是借助ATL库编写的,代码如下:
// 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。

1)
class CFunctionInstanceCollection : public IFunctionInstanceCollection  
{
public:
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID IID, void **pv) throw()
{ return 0; };
ULONG STDMETHODCALLTYPE AddRef(void) throw()
{ return 0; };
ULONG STDMETHODCALLTYPE Release(void) throw()
{ return 0; };
virtual HRESULT STDMETHODCALLTYPE GetCount(__RPC__out DWORD *pdwCount)
{ return 10; };
};

2)从GetInstanceCollection中,我正在做:
*ppIFunctionInstanceCollection = new CFunctionInstanceCollection();
我希望将上述CFunctionInstanceCollection的有效实例赋值给GetInstanceCollection()方法的最后一个参数,即*ppIFunctionInstanceCollection。我已经在服务器端验证了这一点,它打印了有效的指针,类的大小为 4(虚函数的存在产生的类大小为 4)。

但在客户端,值为 NULL。我认为在客户端/服务器之间传递参数还有更多的东西。如果您还看到任何其他内容,请也告诉我。谢谢!!!

最佳答案

抱歉,如果我告诉你一些你已经知道的事情。

在 RPC(和 COM)中,proxy是客户端在调用远程过程时实际调用的一段代码。代理通常对输入参数进行编码,然后将请求发送到服务器,其中一段代码称为 stub解码参数,然后使用它们来调用被调用的实际过程。

当被调用的过程返回结果时, stub 编码输出参数和结果并将响应发送回代理,代理依次解码输出参数等并将它们返回给客户端。

无论如何,这就是一般模型,有时会优化事物(例如,在进程中的 COM 对象的情况下),在这种情况下,可能没有实际的 stub 和实际的代理。尽管如此,这仍然是我们可以用来理解什么是“代理”和“ stub ”的背景。

“空引用指针已传递给 stub ”错误表明问题发生在 stub (即服务器)端。可能将事物传递给 stub 的两段代码是代理和 GetInstanceCollection 的实现,其中 GetInstanceCollection 更可能是罪魁祸首。

我怀疑您的问题是 GetInstanceCollection 实现没有为 *ppIFunctionInstanceCollection 分配值。

尝试在 GetInstanceCollection 返回之前添加代码以分配 *ppIFunctionInstanceCollection。

3/15 更新

您更新后的 GetCount 实现返回值 10。但是,这将被解释为 HRESULT 10 而不是计数值 10。GetCount 的实现应该看起来像这样......

virtual HRESULT STDMETHODCALLTYPE GetCount(__RPC__out DWORD *pdwCount)
{
*pdwCount = 10;
return S_OK;
};

也就是说,虚拟化 IUnknown 方法(QueryInterface、AddRef 和 Release)确实不是一个好主意,因为您可能会意外地破坏各种事情。例如,每次您调用 GetInstanceCollection 时,您的程序都会泄漏一个 CFunctionInstanceCollection 实例,因为它会被创建并且从未被销毁。

您拥有的代码可以用于实验,但最好使用 ATL 为 CFunctionInstanceCollection 执行 IUnknown 的完整实现,就像您为 FunctionDiscovery 类所做的那样。

3/16 更新

为了完整起见,我可能还应该提到,以您的方式分配 *ppIFunctionInstanceCollection 是有效的,但通常可能存在风险。

您已经编写了 CFunctionInstanceCollection 类,因此您知道它直接实现了 IFunctionInstanceCollection 接口(interface),因此您知道您的分配是安全的。但在更一般的情况下,您没有编写类,CFunctionInstanceCollection 类可能会做一些不那么直接的事情 - 例如,它可能会聚合一些其他实现接口(interface)的类。为了真正安全,您应该使用 QueryInterface 来检索 IFunctionInstanceCollection 接口(interface)指针。

关于com - 从 COM 库传递对 COM 接口(interface)的引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5286677/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com