Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/36.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
从COM库传递对COM接口的引用_Com - Fatal编程技术网

从COM库传递对COM接口的引用

从COM库传递对COM接口的引用,com,Com,如何从COM库中将对COM接口的引用作为参数传递 以下是示例: 1) 客户端代码成功创建了coclass,并在pFunctionDiscovery中接收接口指针,如下所示: hr = CoCreateInstance( __uuidof(FunctionDiscovery), NULL, CLSCTX_INPROC_SERVER, __uuidof(IFunctionDiscovery), (LPVOID*)&

如何从COM库中将对COM接口的引用作为参数传递

以下是示例:

1) 客户端代码成功创建了coclass,并在pFunctionDiscovery中接收接口指针,如下所示:

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所做的)