• 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:TestVSworkSpaceRichTxtboxTestIMWpfLibinDebugIMWpfLib.dll
    16     //TlbExp G:TestVSworkSpaceRichTxtboxTestIMWpfLibinDebugIMWpfLib.dll  /out:IMWpfLib.tlb
    17 
    18     //regasm G:TestVSworkSpaceRichTxtboxTestIMWpfLibinDebugIMWpfLib.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:TestVSworkSpaceRichTxtboxTestIMWpfLibinDebugIMWpfLib.dll(开发环境中这一步vs会帮你自动完成,不要奇怪为什么不注册也可以用)

      regasm.exe所在目录C:WindowsMicrosoft.NETFramework64v4.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:TestVSworkSpaceRichTxtboxTestIMWpfLibinDebugIMWpfLib.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中可以弹框,返回结构体等等,比前文的方法功能更强大,不过开发和部署都要稍微麻烦一些,各位可根据自己情况选择

  • 相关阅读:
    linux Mysql 安装
    百度地图的一些操作
    Angularjs Table
    liunx安装mongodb
    ARP协议
    Python获取IP的方式与意义
    selenium 的使用--持续更
    使用pyquery
    beautiful soup的用法
    内置函数
  • 原文地址:https://www.cnblogs.com/flyDream12315/p/6142557.html
Copyright © 2020-2023  润新知