C++调用dotnet-第二节(COM方式)

                                           C++调用dotnet-第二节(COM方式)

                                                                -------托管代码封装成com方式

注:目前非托管C++调用.NET托管代码,主要有两种方式(1.通过CLR提供的接口CLRRuntimeInfo在c++中加载clr然后通过clr调用托管代码;2.讲dotnet托管代码封装成com的方式)本文先讲解第一张

 

第一种方式与第二种方式对比:

CLR Hosting宿主方式:

                               A劣势: 调用方法签名只能是固定的形式[static int mathName(string paramstr))];另外在测试过程中发现弹窗操作提示为非法操作(理解为不能进行弹窗等涉及安全的操作);c++方调用较                                            为复杂(不过形式固定,第一次封装后,后面就方便了)

                               B优势:托管语言开发简单,部署简单方便

COM封装托管代码方式:

                               A劣势:开发较第一种复杂(需要托管代码中按com的开发模式进行封装,加载到GAC中还需要强命名)、部署环境也复杂(需要注册COM)

                               B优势:形式多样,可以继续弹框,甚至参数可以是类,结构体等;c++调用时方便

 

这种方式托管代码放比较麻烦,需要强命名(不加载到GAC可以不签名)

第一步允许与com互操作,项目右键属性勾选或者AssemblyInfo添加代码[assembly: ComVisible(true)]

 

下面是AssemblyInfo.cs代码内容:

 

 1 using System.Reflection;
 2 using System.Runtime.CompilerServices;
 3 using System.Runtime.InteropServices;
 4 using System.Windows;
 5 using System.EnterpriseServices;
 6 
 7 // 有关程序集的常规信息通过以下
 8 // 特性集控制。更改这些特性值可修改
 9 // 与程序集关联的信息。
10 [assembly: AssemblyTitle("IMWpfLib")]
11 [assembly: AssemblyDescription("")]
12 [assembly: AssemblyConfiguration("")]
13 [assembly: AssemblyCompany("")]
14 [assembly: AssemblyProduct("IMWpfLib")]
15 [assembly: AssemblyCopyright("Copyright ©  2016")]
16 [assembly: AssemblyTrademark("")]
17 [assembly: AssemblyCulture("")]
18 [assembly: AssemblyKeyFileAttribute(@"IMWpfLib.snk")]
19 
20 // 将 ComVisible 设置为 false 使此程序集中的类型
21 // 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型,
22 // 则将该类型上的 ComVisible 特性设置为 true。
23 [assembly: ComVisible(true)]
24 
25 // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
26 [assembly: Guid("69423b07-6bfb-473c-8a1f-443596dbf209")]
27 
28 // 程序集的版本信息由下面四个值组成:
29 //
30 //      主版本
31 //      次版本 
32 //      生成号
33 //      修订号
34 //
35 // 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
36 // 方法是按如下所示使用“*”:
37 // [assembly: AssemblyVersion("1.0.*")]
38 [assembly: AssemblyVersion("1.0.0.0")]
39 [assembly: AssemblyFileVersion("1.0.0.0")]

 

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 
 6 
 7 using System.Runtime.InteropServices;
 8 using System.Windows;
 9 using System.EnterpriseServices;
10 namespace IMWpfLib
11 {//sn -k IMWpfLib.snk
12     //gacutil -i IMWpfLib.dll
13     //tlbexp IMWpfLib.dll /out:IMWpfLib.tlb
14 
15     //    gacutil -i G:\TestVSworkSpace\RichTxtboxTest\IMWpfLib\bin\Debug\IMWpfLib.dll
16     //TlbExp G:\TestVSworkSpace\RichTxtboxTest\IMWpfLib\bin\Debug\IMWpfLib.dll  /out:IMWpfLib.tlb
17 
18     //regasm G:\TestVSworkSpace\RichTxtboxTest\IMWpfLib\bin\Debug\IMWpfLib.dll
19     [Guid("087195E0-DA0D-40E2-AF4C-0C9EDE95D425")]
20     public interface IMLibInterface
21     {
22         [DispId(1)]
23         MainWindow NewImWindow();
24 
25         [DispId(2)]
26         void ShowWindows(Window showWindow);
27 
28         [DispId(3)]
29         IMCtrl NewContro();
30 
31         [DispId(4)]
32         void ShowWindowsTest();
33 
34         [DispId(5)]
35         void ShowWindowsTest2();
36 
37     }
38     [Guid("C099A746-4733-4523-B324-683A9E9F3416")]
39     [ClassInterface(ClassInterfaceType.None)]
40     public class IMComInterop : ServicedComponent, IMLibInterface
41     {
42         public IMComInterop()
43         {
44 
45         }
46 
47 
48         public MainWindow NewImWindow()
49         {
50             return new MainWindow();
51         }
52 
53         public void ShowWindows(Window showWindow)
54         {
55             showWindow.Show();
56         }
57 
58         public IMCtrl NewContro()
59         {
60             return new IMCtrl();
61         }
62         public void ShowWindowsTest()
63         {
64             MainWindow a = new MainWindow();
65             a.ShowDialog();
66         }
67         public void ShowWindowsTest2()
68         {
69             Console.Write(1 + 1);
70         }
71     }
72 }

执行上述代码后通过C:\Program Files (x86)\Microsoft SDKs  下面的工具(根据.NET版本选择不同版本的工具)生成tlb com接口定义库给c++用

A.生成强命名秘钥:sn -k IMWpfLib.snk

B.在AssemblyInfo.cs中添加代码[assembly: AssemblyKeyFileAttribute(@"IMWpfLib.snk")]

C.重新编译dll,将其copy到c++的exe所在目录或者注册到GAC中(gacutil -i IMWpfLib.dll)

D.regasm注册com组件:regasm G:\TestVSworkSpace\RichTxtboxTest\IMWpfLib\bin\Debug\IMWpfLib.dll(开发环境中这一步vs会帮你自动完成,不要奇怪为什么不注册也可以用)

  regasm.exe所在目录C:\Windows\Microsoft.NET\Framework64\v4.0.30319

 检验方式可以在.NET项目中添加引用里面选择com,查看有没有对于dll名字的com项

E.生成tlb:tlbexp IMWpfLib.dll /out:IMWpfLib.tlb

 

非托管C++代码

 1 // ImportCsharp.cpp : 定义控制台应用程序的入口点。
 2 //
 3 
 4 #include "stdafx.h"
 5 #include <iostream>
 6 #include "DotNetRuntimeWrap.h"
 7 
 8 #import "G:\TestVSworkSpace\RichTxtboxTest\IMWpfLib\bin\Debug\IMWpfLib.tlb" raw_interfaces_only 
 9 
10 
11 //static void TestClrHost()
12 //    {
13 //
14 //    DotNetRuntimeWrap dotNetWrap;
15 //    dotNetWrap.Loader(L"v4.0.30319", L"CLRHostLib.dll", 
16 //        L"CLRHostLib.ClrClass",L"ClrExcute");
17 //
18 //    }
19 static void TestCom()
20     {
21 
22     CoInitialize(NULL);//一定要初始化
23     IMWpfLib::IMLibInterfacePtr ptr; //生成的
24     ptr.CreateInstance(__uuidof(IMWpfLib::IMComInterop));//创建智能指针
25 
26     //IMWpfLib::_MainWindow **ptrMP=NULL;
27     ptr->ShowWindowsTest2();
28 
29     ptr->ShowWindowsTest();
30 
31     }
32 
33 
34 
35 int _tmain(int argc, _TCHAR* argv[])
36     {
37 
38     //TestClrHost();
39     TestCom();
40     return 0;
41     }

执行结果如下:正常调用,托管dll中可以弹框,返回结构体等等,比前文的方法功能更强大,不过开发和部署都要稍微麻烦一些,各位可根据自己情况选择

 

 

posted @ 2016-12-07 20:14  gaofeidemeng  阅读(796)  评论(1编辑  收藏  举报