各位COM高手和COM初学者,请你们说说COM的 proxy/stub程序实现时的相关问题,谢谢!!!请大家说说自己的所知,经验,和问题, 非常感谢!!!编写COM时需要使用proxy/stub程序,请教proxy/stub的产生和使用:1.
是否选择生成proxy/stub选项后编译成的DLL含有proxy/stub程序?
2.
A. 如果proxy/stub程序(DLL)是独立的,那幺这个COM 只要有接口的定义,然后编译成DLL就行了?B. 如果proxy/stub程序(DLL)是独立的,那幺具体的COM接口实现的DLL要怎幺实现?是不是要用到_MERGE_PROXYSTUB,这个东西怎幺用?(ATL的向导中有这个选项,MFC中没有它那样怎幺办?)
具体的COM接口实现与那些不要使用proxy/stub程序的COM接口的实现在代码的写法上有什幺不同?(看到一样例代码中有如下写法,是什幺意思?有什幺作用?:
#ifdef _MERGE_PROXYSTUB
    if( !PrxDllMain( hInstance, dwReason, lpReserved ) )
        return FALSE;
#endif
    hInstance;
    return _AtlModule.DllMain( dwReason, lpReserved ); 
)C. 如果proxy/stub程序(DLL)是独立的,那幺一个COM有两个DLL,这样程序安装时,客户端和服务端是不是都需要这两个文件?
3.
如果proxy/stub程序(DLL)不是独立的,而是的COM接口的具体实现是在一起的,那幺这个COM和那些不要使用proxy/stub程序的COM的编写有什幺不同?
(如果是使用MFC时,它的向导中没有Allow merging of proxy/stub code这个选项,又需要怎幺做?)

解决方案 »

  1.   

    if your server is in-process server,and your know clearly that
    your server and client run on same machine,you can merge the 
    proxy/stub object with the server dll,otherwise,you should 
    produce the proxy/stub dll and deployee it on the client machine
    and server machine.the dll is <your application name>PS.dll------I can only type English words because my machine cannot 
    type Chinese words.
      

  2.   

    to wangweixing2000:
    謝謝你的回答!你能不能一個一個的詳細點?
      

  3.   

    我已经很久没有碰过COM了,基本都忘了,翻了下MSDN及代码,大致回想起一些,可能有些疏漏,还请见谅了。
    首先应明确Proxy/Stub不是必须的,其次的重点是它其实是一个COM组件,实现了一些必要的标准接口,如IRpcProxyBuffer之类。当在跨套间使用COM接口时,应先调用CoMarshalInterface进行Proxy/Stub组件的CLSID及相关信息的列集,然后再调用CoUnmarshalInterface以生成真正的Proxy/Stub组件对象,并使用(对此我在《COM线程模型》中大致说明了一下)。由于Proxy/Stub是COM组件,因此其有一个CLSID。在CoUnmarshalInterface中,先根据传过来的已列集的数据中的IID,查找注册表中HKEY_CLASSES_ROOT\Interface\<IID>\ProxyStubClsid32键值,是一个字符串类型,记录了相应<IID>所对应的COM接口的Proxy/Stub组件的CLSID。然后CoUnmarshalInterface中,再根据这个CLSID按最正常地步骤生成Proxy/Stub组件对象并聚合之,然后返回相应的代理接口。
    所以Proxy/Stub组件就和普通的COM组件一样,需要注册。当这个组件是DLL实现的,就响应DllRegisterServer之类的函数,也就是楼主给出的代码中宏_MERGE_PROXYSTUB的作用(当已经定义过它时,就编译进对PrxDllRegisterServer之类的调用。楼主的PrxDllMain是同样道理——正常COM组件需要的初始化,Proxy/Stub组件也需要)。所以那个_MERGE_PROXYSTUB宏只不过是VC向导生成的一个辅助配置宏,当用MFC实现COM组件时,如果是DLL的,那么也有DllMain(不过被MFC重载了,所以应在CWinApp::InitInstance中对PrxDllMain调用),也有DllRegisterServer之类的函数,相应地加上PrxDllRegisterServer之类的函数(在MIDL生成的dlldata.c实现)就可以了。也就是说PrxDllRegisterServer专门用于注册用MIDL生成的Proxy/Stub组件(实际调用NdrDllRegisterProxy)。所以如果需要当COM组件的实现是EXE时仍混合Proxy/Stub组件的代码(这是有意义的,至少就可以少掉DLL中无聊的重定位表那个大头,虽然现在生活富裕了),只需要在你认为可能需要使用到Proxy/Stub组件前,调用CoRegisterClassObject注册Proxy/Stub组件的CLISD,再调用CoRegisterPSClsid将这个CLSID和相应的IID绑定起来。而对于Proxy/Stub组件的CLSID,是利用rpcproxy.h中的GET_DLL_CLSID宏,在MIDL生成的dlldata.c中被使用。工程中,在要使用它之前包含rpcproxy.h即可。亦或是使用rpcproxy.h中另一个宏PROXY_CLSID,即修改dlldata.c,在其开头如下:
    #define PROXY_CLSID g_PS_CLSID
    而变量g_PS_CLSID则可在工程中的任意一个源文件中定义。这样g_PS_CLSID的值将作为MIDL生成的Proxy/Stub组件的CLSID。