当前位置:天才代写 > tutorial > C语言/C++ 教程 > 利用IDispatch::Invoke函数在C++中挪用C#实现的托管类库要领

利用IDispatch::Invoke函数在C++中挪用C#实现的托管类库要领

2017-11-04 08:00 星期六 所属: C语言/C++ 教程 浏览:589

副标题#e#

CLR Interop简而言之是让非托管代码与托管代码之间可以彼此挪用的技能。这项技能可以使开拓人员重用已有的托管或非托管组建,并按照本身的需要,衡量托管代码的浅易性与非托管代码的机动性,选择适合本身实际环境的编程语言,而不消过多思量重用的组件是用哪种语言开拓的。Interop中文的意思是互通性,既然是互通,代码的挪用就有两种差异的偏向。本文所要报告的是利用COM Interop技能在非托管代码方如何挪用托管代码。

1. 建设托管处事器

首先让我们在Visual Studio 2008建设一个C#的Class Library(类库)项目,取名为MyManagedServer,在该项目中,我们要声明并实现一个接口。

接口声明代码如下:

为了说明简朴,该接口中只有一个要领,用于打印一些信息。个中的ComVisible属性至关重要,当它的值为true时,该接谈锋对COM可见。

view plaincopy to clipboardprint?

1.using System;
2.using System.Runtime.InteropServices;
3.
4.namespace MyManagedServer
5.{
6. [ComVisible(true),
7. Guid("79EDDA1C-F243-47C5-8954-5DEF01FA3D44"),
8. InterfaceType(ComInterfaceType.InterfaceIsDual)]9. public interface IManagedFooClass
10. {
11. [PreserveSig, DispId(1)]12. void PrintFoo();
13. }
14.}


#p#副标题#e#

接下来是实现该接口的类:

view plaincopy to clipboardprint?

1.using System;
2.using System.Runtime.InteropServices;
3.
4.namespace MyManagedServer
5.{
6. [ComVisible(true),
7. ClassInterface(ClassInterfaceType.AutoDual),
8. ProgId("MyManagedServer.ManagedFooClass")
9. ]10. public class CustomCOMClient :
11. IManagedFooClass,
12. IManagedBarClass
13. {
14. public CustomCOMClient()
15. {
16. }
17.
18. #region IManagedFooClass Members
19.
20. [DispId(1)]21. public void PrintFoo()
22. {
23. Console.WriteLine("in MyManagedServer: CustomCOMClient.PrintFoo()");
24. }
25.
26. #endregion
27. }
28.}

这里我们给这个类的ProgId属性赋一个值。等会儿在注册组件的时候,注册表中将会增加一个键值,将ProgId和runtime为我们自动生成的CLSID关联起来。

#p#副标题#e#

2. 为COM Interop注册托管处事组件

注册组件可以用Visual Studio帮我们自动注册,也可以在呼吁行下手动输入呼吁。若要利用Visual Studio来帮我们注册组件,只需在项目属性页(鼠标右键项目名称,在下拉菜单中选择“Properties(属性)”)的Build标签页中把Register for COM Interop项打上勾,然后再build项目就可以了。如下图所示:

操作IDispatch::Invoke函数在C++中调用C#实现的托管类库方式

另外,我们也可以先build项目,然后通过呼吁行的方法注册组件。只需要利用regasm.exe在VS2008呼吁行下输入如下呼吁即可:

regasm assemblyname.dll /tlb /codebase

该呼吁会为我们注册组件,生成并注册对应的type library文件。个中assemblyname.dll是项目构建生成的措施集文件。

3. 建设非托管客户端

利用托管语言建设并注册了组建之后,我们就要利用非托管语言来实验通过COM Interop挪用组建中的要领了。首先,在Visual Studio 2008中建设一个Visual C++ Win32 Console Application,取名为MyNatvieClient,并将组建生成tlb文件拷贝至该项目标源代码目次中。然后在MyNativeClient.cpp中输入如下代码:

view plaincopy to clipboardprint?

1.#include "stdafx.h"
2.
3.#import "mscorlib.tlb" no_namespace
4.#import "MyManagedServer.tlb" no_namespace
5.
6.int _tmain(int argc, _TCHAR* argv[])
7.{
8.
9. ::CoInitialize(NULL);
10.
11. // Get CLSID for CoCreateInstance
12. const OLECHAR lpszProgID[] = OLESTR("MyManagedServer.ManagedFooClass"); 13. CLSID clsid;
14. HRESULT hr = CLSIDFromProgID(lpszProgID, &clsid);
15. if(SUCCEEDED(hr))
16. {
17. printf("CLSIDFromProgID Succeeded \n");
18. IDispatch* ppv = 0;
19. HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_ALL, IID_IDispatch, (void**)&ppv);
20.
21. if(SUCCEEDED(hr))
22. {
23. printf("CoCreateInstance Succeeded \n");
24.
25. // Get DispId for Invoke
26. DISPID dispid;
27. const LPOLESTR szMember = OLESTR("PrintFoo");
28. HRESULT hr = ppv->GetIDsOfNames(IID_NULL, (LPOLESTR*)&szMember,1,LOCALE_SYSTEM_DEFAULT,&dispid);
29. if(SUCCEEDED(hr))
30. {
31. printf("GetIDsOfNames Succeeded \n");
32.
33. // There's no parameter to pass
34. DISPPARAMS dispParams = {0};
35. VARIANT vtResult;
36. UINT dwArgErr;
37.
38. HRESULT hr = ppv->Invoke(dispid,IID_NULL,NULL,DISPATCH_METHOD,
39. &dispParams,&vtResult,NULL,&dwArgErr);
40. if(SUCCEEDED(hr))
41. {
42. printf("Invoke Succeeded \n");
43. }
44. }
45.
46. ppv->Release();
47. }
48. }
49.
50. return 0;
51.}

#p#副标题#e#

该代码主要做了以下几件工作:

a. 挪用CoInitialize举办初始化。

b. 挪用CLSIDFromProgId得到工具的CLSID,因为接下来的函数将通过CLSID来建设实例。

c. 通过CoCreateInstance建设工具实例。这里建设的是一个IDispatch的工具实例。

d. 挪用IDispatch::GetIDsOfNames以得到将要挪用的要领的DispID,供接下来的函数利用。

e. 利用IDispatch::Invoke来挪用要领。

#p#分页标题#e#

在import type library的时候我们不只import了组建的tlb文件,同时还import了mscorlib.tlb以制止生成的姑且的tlh文件中一些范例找不到的环境。(有关此方面的问题可以参考我们团队开拓人员张羿撰写的《#import从.NET DLL生成的tlb的神秘错误》)

编译通事后运行功效,可看到呼吁行中打印出如下信息:

CLSIDFromProgID Succeeded
CoCreateInstance Succeeded
GetIDsOfNames Succeeded
in MyManagedServer: CustomCOMClient.PrintFoo()
Invoke Succeeded

注:本文所示代码只作为实例利用。本文作者差池因代码利用不妥而造成的问题认真。v

 

    关键字:

天才代写-代写联系方式