首页 > 编程语言 >C#与C++代码的互操作方式

C#与C++代码的互操作方式

时间:2024-01-14 20:56:46浏览次数:44  
标签:调用 C# 代码 Interop C++ -- 互操作 COM

title: C#与C++代码的互操作方式
date: 2024-01-10
categories: 编程
tags:
- C#
- .NET
- C++
- COM
- 平台调用

大致介绍

在写C#程序时经常有与本地代码(C/C++)代码交互的需求。微软提供了许多种方式供我们选择,
最常用的有以下三种(A->B指A可以引用B):

flowchart LR A--P/Invoke-->B A<--C++ Interop-->C A<--COM Interop-->D D<-->C-->B subgraph 托管环境 A[.NET应用程序] end subgraph 非托管环境 B[C 库函数] C[C++ 类库] D[COM组件] end
  • P/Invoke (Platform Invoke):平台调用,是一种用于和非托管函数进行交互的技术,
    在调用Windows API的时候有大量的运用。特点是无需编写兼容层代码即可使用。
  • C++ Interop:托管C++,使用C++/CLI (Common Language Infrastructure)语言,
    特点是可以将托管代码和非托管代码写在一个文件/程序集里,从而使得它十分灵活,它本质上还是平台调用。
  • COM (Component Object Model):组件对象模型,是微软早在.NET出现之前就提出的一种Windows开发技术,
    现在Windows中到处都有它参与。虽然它是很老的技术,但在最新的技术中也可以看到它的身影(如WinUI3)。
    需不需要写兼容层代码取决于原来的代码有没有使用COM,如Win32就没有使用,而WinRT使用了。

那么如何从这之中选择呢?以下列出了三种方式的大致区别:

P/Invoke C++ Interop COM Interop
支持平台 全平台 仅Windows 理论上全平台
语言 标准C/C++ C++/CLI IDL
导出对象 函数
引用方式 DllImport 直接引用 ComImport
上手难度 几乎无难度 简单 复杂
兼容层代码 不需要 需要 可能需要

性能测试

选择一种技术最重要的指标就是效率了,我测试了三种技术分别在大量调用、大量执行次数情况下的表现情况。
调用次数是由托管代码实现的(即调用Test的次数),执行次数是由本地代码实现的(即传入的参数executions)。
我选择了IsWindows10OrGreater函数进行调用测试:

HRESULT Test(int executions)
{
    for (int i = 0; i < executions; ++i)
    {
        IsWindows10OrGreater();
    }
    return S_OK;
}

源代码可以参见仓库[1]
我在Windows11 64位系统下运行,使用.NET 8运行时,以下是测试结果:

调用/执行次数 P/Invoke C++ Interop COM Interop
1000000/1 01.162s 01.327s 32.504s
1/1000000 01.054s 01.294s 01.063s

可见除了大量调用COM,其他的方法效率都差不多。这是因为每次调用COM都会产生一个COM对象,
从而导致速度很慢。三种方法都有类型封送(Marshal)操作,这也是最花时间部分,所以使用时间都差不多。
可以从下面流程图了解大致流程:

P/Invoke流程图

flowchart LR B-->C-->F--平台调用<br/>封送处理-->G D~~~E subgraph 非托管 subgraph G[DLL] A[非托管函数] end end subgraph 托管 B[托管源代码] C[编译器] subgraph CLR subgraph F[程序集] direction TB D[元数据] E[IL代码] end end end

COM流程图

flowchart LR X--IDispatch---F Y--ISimpleCOMCalculator---F Z--IUnknown---F A-->B C-->D-->B-->E-->Y subgraph 托管代码 A[托管应用程序] B[元数据代理] C[COM组件类型库] D([类型库导入程序<br/>TlbImp.exe]) end E[运行库课调用包装<br/>RCW] subgraph 非托管COM代码 F[COM对象] X(( )) Y(( )) Z(( )) end

个人看法

P/Invoke的两端是标准的C/C++和标准的C#(.NET)代码,是保持可移植性、可读性的不二之选。
平台调用流程相对简单,过程更加透明,在绝大多数情况下都应该选择它。
但它的缺点是无法导出类,如果大型项目有面对对象的需求(类似于DirectX)则不是最优选择。

C++ Interop灵活性非常高,可以准确控制封送过程,所以性能理论上也更好。
但是缺点[2]也更严重,它只能面向Windows平台,
很多情况下这个缺点是不能接受的。如果目标项目是只面向Windows平台(如WinForm,WPF等),
且要调用大量本地API,而且对性能要求较苛刻的情况下,可以考虑使用。

COM有着很复杂的内部结构,学习成本较高。如果写小型项目,即使有面向对象的需求也不需要使用它。
但如果接触Windows平台编程,几乎绕不开调用COM,所以也要对调用COM代码有一定程度的了解。
同时也要避免创建大量COM对象,这可能导致性能低下。

可以参考《精通.NET互操作 P/Invoke,C++Interop和COM Interop》[3]这本书来学习。


  1. InteropPerformanceTest ↩︎

  2. C++/CLI .NET Core 限制 ↩︎

  3. 《精通.NET互操作 P/Invoke,C++Interop和COM Interop》 黄际洲 崔晓源 著 ↩︎

标签:调用,C#,代码,Interop,C++,--,互操作,COM
From: https://www.cnblogs.com/pokersang/p/17964168

相关文章

  • ICMP流量—CTFGHUB技能树
    简介ICMP(InternetControlMessageProtocol)互联网控制消息协议,和IP一层,但ICMP使用时必须增加IP报头。属于网络层协议,它用于TCP/IP网络中发送控制消息,用于在IP主机、路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。这些控制消......
  • CSS浮动&定位&布局
    浮动简介浮动最早起设计出来是为了实现文字环绕图片或者文字环绕的效果,现在浮动是主流的页面布局方式之一float:浮动属性,值可以是left、right对应向左和向右浮动元素浮动之后的特点脱离文档流不管浮动前是什么元素,浮动后,默认宽高都是被内容撑开,而且可以设置宽高不......
  • 作为所有类的顶层父类,没想到Object的魔力如此之大!
    写在开头在上一篇博文中我们提到了Java面向对象的四大特性,其中谈及“抽象”特性时做了一个引子,引出今天的主人公Object,作为所有类的顶级父类,Object被视为是James.Gosling的哲学思考,它高度概括了事务的自然与社会行为。源码分析跟进Object类的源码中我们可以看到,类的注释中对它......
  • 微信请求封装:wx.request,wxCloud
    wx.request//方式一console.log('环境==',envVersion);//consthost="https://springboot-hebq-84640-6-1323095709.sh.run.tcloudbase.com";consthost="https://t.jiazhangq.cn";constwxRequest=function(params,url){consol......
  • pycharm常用设置
    一、在使用pycharm的时候有时候会遇到编码问题pycharm设置模板,每次创建文件都会默认在前面加上utf-8,操作如下  FileEncoding中设置编码 二、设置编码                                   ......
  • 存入cookie中的数据变成了[object%20Object] 原因及处理
    原因在JavaScript中,当你尝试将一个对象直接存储到cookie中时,浏览器会将对象调用toString方法将其转换为字符串。对于大多数JavaScript内置对象,toString方法会将对象转换为字符串"[objectObject]"。因此,当你尝试将一个对象存储到cookie中时,实际上是将"[objectObject]"这个字符串......
  • C++U6-02-最短路算法1-dijkstra迪杰斯特拉最短路径
    学习目标 最短路径的基本概念  练习1 最短路的定义 本节课迪杰斯特拉dijkstra最短路算法 算法流程:以下是Dijkstra最短路径算法的逐步计算松弛的过程:初始化起始节点的距离为0,其他节点的距离为无穷大。选择当前距离最小且未被访问的节点作为当前节点。......
  • Office软件正版安装(无需第三方激活)
    Office软件正版安装(无需第三方激活)下载安装office软件部署工具:https://www.microsoft.com/en-us/download/details.aspx?id=49117下载完后双击打开,会将文件解药到指定目录office版本自定义工具:https://config.office.com/deploymentsettings选择位数选择Office套件,选......
  • Rsync未授权访问漏洞
    开设这个随笔主要是因为最近在学习王放do9gy老师的web漏洞解析与攻防实战。顺便完成里面的配套实验了,其实大部分靶场都是来在vulhub,相当于对人家的靶场进行依次复现了。内容可以在https://vulhub.org/#/environments/rsync/common/见到。毕竟理论是理论,实战是实战。搭建个靶场......
  • 使用TVertScrollbox自定义列表数据
    界面布局设置如下创建一个过程添加新项目procedureTForm1.AddItem(name:string;age:Integer);varlayout:TLayout;begin//设置姓名标签的文本Label3.Text:=name;//设置年龄标签的文本Label4.Text:=IntToStr(age);//克隆Layout1,并将克隆得到......