com对象跨线程

By admin at 2019-09-12 • 0人收藏 • 1511人看过

不建议com对象传递到其他线程, 这样违反了com的设计初衷



以下只是测试:

参考贴:

https://docs.microsoft.com/en-us/previous-versions/windows/embedded/ms887793(v=msdn.10)?redirectedfrom=MSDN


https://blog.csdn.net/xbgprogrammer/article/details/7353921


https://technet.microsoft.com/zh-cn/sysinternals/ms682465(v=vs.110)


https://docs.microsoft.com/zh-cn/windows/win32/api/objidl/nf-objidl-iglobalinterfacetable-registerinterfaceinglobal

import com.interface; 
namespace com.interface;

class comShare{
	ctor(){
		this = ..com.interface.IUnknown(); 
	}; 
	pointer RegisterInterfaceInGlobal = "INT(pointer pUnk,struct riid, INT& pdwCookie)";
    pointer GetInterfaceFromGlobal = "INT(INT dwCookie,struct riid,pointer& ppv)";
    pointer RevokeInterfaceFromGlobal = "INT(INT dwCookie)";
}
comShare.IID = "{00000146-0000-0000-C000-000000000046}";
 
comShare.Create = function(){ 
	var activationManager  =  ..com.interface.create( "{00000323-0000-0000-C000-000000000046}" 
		, comShare, 0x1/*_CLSCTX_INPROC_SERVER*/  );
		 
	return activationManager;
}
          
/**intellisense()
com.interface.comShare.Create() = !comShare.
!comShare.AddRef() = 引用计数加一,返回引用计数
!comShare.Release() = 引用计数减一,返回引用计数
!comShare.QueryInterface(__/*接口数*/) = 参数是接口类,参考com.interface.IUnknown源码
!comShare.RegisterInterfaceInGlobal(.(pUnk,riid,pdwCookie) = 注册
!comShare.GetInterfaceFromGlobal(.(dwCookie,riid,ppv) = 获取
!comShare.RevokeInterfaceFromGlobal(.(dwCookie) = 删除
end intellisense**/



winform.button2.oncommand = function(id,event){

 	myRet = com.interface.comShare.Create();
	console.varDump(myRet)
	flcIID = win.guid.fromString("{E08BA07E-6463-4EAB-8437-99F08000BAD9}")
	ret,fcID = myRet.RegisterInterfaceInGlobal(flc,flcIID,0);
	console.varDump(ret);
	console.varDump(fcID);
	console.log("------------------------")
	//上面的都成功返回, 下面这个调用就崩溃,估计类型出错了?
	var ret,flcFun = myRet.GetInterfaceFromGlobal(fcID,flcIID);
	console.varDump(ret);
	console.varDump(flcFun)

	
}


目前上面代码还没有调通. 不知道哪里出问题了,后面慢慢研究

2 个回复 | 最后更新于 2019-09-07
2019-09-12   #1

https://docs.microsoft.com/zh-cn/previous-versions/ms867182(v=msdn.10)

讲述了

Windows Media Player 插件协同工作


就是利用了com跨线程的方式GIT

image.png

2019-09-14   #2

https://www.codeproject.com/Articles/17837/Global-Interface-Table-An-Easy-Way-to-Marshal-an-I


Introduction

Component Object Modeling (COM) and ActiveX Template Library (ATL) are the toughest areas in Windows programming, but as a Windows programmer, you daily encounter these and seldom face difficulty accessing a COM pointer created in one thread from another thread in a multithreaded environment. COM/ATL has the concept of marshalling and the usage of Global Interface table to cope up with this problem.

Here, I am demonstrating how to marshal an interface pointer from one thread to another worker thread with some quick code. ATL provides an interfaces called IGlobalInterfaceTable and a COM template class called CComGITPtr to help the programmer understand this concept easily..

In my example, I have a COM component with an interface IIGitTest, which I am going to marshal in the GitClient application. If you don't know how to create the COM component, please refer to my Step-by-Step Guide for Creating a COM component.

How to marshal the interface pointer from one apartment to another?

  1. First of all, we have to create a component exposing the IIGitTest with get/set property name and then create a MFC dialog based client application GitClient, which will access this interface from one apartment to another?

  2. Our component name is GitInterface. I will import the DLL using a #import directive since I don't want the namespace in the imported tlh and tli files, so I will use the no_namespace suffix with #import. I.e., in our example:

  3. #import "..\\output\\GitInterface.dll" no_namespace
  4. Now we can access our IIGitTest. We now add the member variable in our class like:

  5. IIGitTestPtr m_pToInterface;
  6. Allocate memory to our interface and don't forget to initialize the COM model in the application.

  7. CoInitialize(NULL); // initialize the com CLSID pclsid; CLSIDFromString(L"GitInterface.IGitTest.1",&pclsid); m_pToInterface.CreateInstance(pclsid);
  8. Now, give some values to our interface pointer. This will help us check if we are able to marshal our interface properly.

  9. TCHAR szValues[256];  m_edtGitValue.GetWindowText(szValues,256);  CComBSTR bstrValues(szValues);  m_pToInterface->put_Value(bstrValues);
  10. Now unleash our GIT Code in the client application.

  11. CComGITPtr<IIGITTEST> pToGITTest(m_pToInterface); DWORD dwGitCookie = pToGITTest.Detach();

    You must be wondering what this dwGitCookie will do and how the template class is working? CComGITPtr is a template wrapper class, which encapsulates the IGlobalInterfaceTable interface. We are passing our interface pointer to the template class CComGITPtr, and in return it is returning the DWORD cookie, which will help us find our interface in the global interface table.

  12. Now create a thread which will get the IIGitTest pointer from the Global Interface table.

  13. /// Create thread to try marshalling  CreateThread(NULL,NULL,ThreadProc,     reinterpret_cast<LPVOID>(dwGitCookie),NULL,NULL);
  14. Now, initialize COM inside the new thread, and retrieve the cookie identification which we have sent through the lpParam parameter.

  15. CoInitialize(NULL); DWORD dwCookie = reinterpret_cast<DWORD>(lpParam);
  16. Now create the CComGITPtr object and pass dwCookie as the parameter, which will instruct the CComGITPtr object to search GIT and retrieve the interface pointer of our interface.

  17. CComGITPtr<IIGITTEST>pToGITTest(dwCookie);
  18. Now, just copy the interface pointer to our interface pointer using the CComGITPtr::CopyTO function.

  19. IIGitTest *pToGitPtr; pToGITTest.CopyTo(&pToGitPtr);
  20. Now, retrieve the value. Remeber step 5.

  21. CComBSTR bstValue;  pToGitPtr->get_Value(&bstValue);  MessageBoxW(NULL,bstValue,L"From Git Interface",MB_OK);

    The End :)

In this way, you can marshal an interface pointer from one thread to an other without thinking about the technicality of marshalling and other related stuff. Let us revise the process again.

Quick Revision

  1. Create an interface pointer and attach it to the GIT template class

  2. Retrieve the cookie from the GIT object

  3. In another thread, using a DWORD cookie, find the interface in the GIT table

  4. Copy the object into an interface pointer

  5. Voila, now you can use your interface without any exception :)


下面是附件代码:

gittest.zip


登录后方可回帖

登 录
信息栏
 私人小站

本站域名

ChengXu.XYZ

投诉联系:  popdes@126.com



快速上位机开发学习,本站主要记录了学习过程中遇到的问题和解决办法及上位机代码分享

这里主要专注于学习交流和经验分享.
纯私人站,当笔记本用的,学到哪写到哪.
如果侵权,联系 Popdes@126.com

友情链接
Aardio官方
Aardio资源网


才仁机械


网站地图SiteMap

Loading...