【问题标题】:C++ COM C# Mixed Mode InteroperationC++ COM C# 混合模式互操作
【发布时间】:2010-12-27 07:56:50
【问题描述】:

我正在尝试了解从非托管 C++ 调用 C# 库实现的选项。

我的顶级模块是一个非托管 C++ COM/ATL dll。我想集成现有托管 C# dll 的功能。我有,并且可以重新编译这两个库的源代码。

通过阅读 MSDN 上的 this overviewthis SO question 之类的文章,我了解到可以创建一个“混合模式”dll,它允许本机 C++ 代码调用 C# 库。

我对这种方法有几个问题:

  1. 如何进行设置? 我可以简单地更改一些属性吗 在现有的 COM/ATL 项目上 允许使用 C# 模块?
  2. 这些混合模式调用将如何 与 COM 互操作的性能不同 电话?有没有共同的字符串 可用于防止的格式 之间的转换或深拷贝 模块?
  3. 如果创建了这个 dll 混合模式,还能这样吗 以相同的方式接口/使用 它的 COM 客户端,或者他们需要 了解混合模式吗?
  4. 包含 CLR 是否会带来实质性的影响 加载此 COM 对象时的开销?

我是 Windows 开发新手,所以如果问题陈述中的任何内容需要澄清或更正,请发表评论。

提前致谢。

【问题讨论】:

    标签: c# c++ com com-interop mixed-mode


    【解决方案1】:

    我该如何进行设置?我可以简单地更改现有 COM/ATL 项目的一些属性以允许使用 C# 模块吗?

    如果您完全控制该项目,那么更改此类设置不是问题,那么可以确定。您只需为此项目启用/clr(在项目属性中,打开“常规”页面,并查找“通用语言运行时”支持)。现在,您可以根据需要在项目中使用托管句柄 (^) 和其他 C++/CLI 位。所有用纯 C++ 编写的现有代码都应该继续工作(它现在将尽可能编译为 MSIL,但其语义将保持不变)。

    这些混合模式调用与 COM 互操作调用的性能有何不同?是否有一种通用的字符串格式可以用来防止模块之间的转换或深拷贝?

    混合模式调用会更快,因为它使用更快的调用约定,并且不会像 COM 互操作那样进行任何封送处理(您要么使用本质上兼容的类型,要么进行自己的显式转换)。

    没有通用的字符串格式——问题是System::String 既分配又拥有它的缓冲区,并且还要求它是不可变的;所以你不能自己创建一个缓冲区,然后将其包装为String,或者创建一个String,然后将其用作输出文本的缓冲区。

    如果这个 dll 是在混合模式下创建的,它的 COM 客户端是否仍然可以以相同的方式接口/使用它,或者它们是否需要支持混合模式?

    它的接口可以相同,但如果它是通过本机入口点进入的,它将尝试将 CLR 加载到进程中,除非已经加载了一个。如果调用客户端在调用之前已经加载了 CLR(或者客户端本身是从托管代码调用的),那么您将获得已经加载的 CLR,这可能与您的代码所需的 CLR 不同(例如客户端可能已经加载了 1.1,而你的代码需要 2.0)。

    在加载此 COM 对象时,包含 CLR 是否会产生大量开销?

    这取决于您对开销的定义。代码大小?运行时惩罚?内存占用?

    无论如何,加载 CLR 意味着您获得了所有 GC 和 JIT 机器。那些都不便宜。也就是说,如果您最终需要调用托管代码,则无法解决这个问题 - 您将必须将 CLR 加载到某个进程中来执行此操作。 COM Interop 和混合模式 C++/CLI 程序集之间的惩罚不会有所不同。

    【讨论】:

    • 感谢您提供的所有重要信息。我希望我能投不止一张赞成票。
    • 非常有偏见的意见。 COM 调用并不慢。 CLR 加载开销很大。
    • 解释 COM 调用如何不会变慢,如果它使用的调用约定要求将所有参数推入堆栈(无注册表内传递),而直接托管本机 C++/CLI调用将使用“thiscall”。此外,当使用/clr 时,大多数代码将首先编译为 MSIL——ref 和非ref 类——因此在 DLL 入口点和从那里都是管理的,没有过渡惩罚。我已经说过 CLR 加载开销很大,但是如何通过 COM 互操作(或其他方式)避免它?
    • 这个电话?但是他的方法没有参数或 10+ 参数 :-)) 所以你的速度比较偏向于 1-2 参数方法......
    • 一个“无参数”的实例方法仍然有 1 个参数 - this
    【解决方案2】:

    我不能说太多细节,例如字符串问题,因为我从未积极使用过这种方法。

    但是您可以轻松地使用任何 C# 代码中的任何 COM 接口,只需让 VS 向导为您创建一个代理即可,除了调用 COM 和 .NET 时始终存在的性能开销之外,它没有任何性能开销。

    另一个方向,您只需将 C# 程序集的 ComVisibleAttribute 设置为 true(在 VS 中,它是项目属性中的一个简单复选框),然后编译器会自动为您创建 COM 接口。同样,没有额外的性能损失。

    HTH!

    【讨论】:

    • “没有额外的性能损失” - 与什么相比额外?
    • 与“除了调用 COM 和 .NET 时始终存在的性能开销之外没有任何性能开销”相比,就像我之前说过的几行。提示:阅读有助于...
    • 仍然无法解析。 “没有额外的惩罚”适用于通过 COM 调用 .NET(因为您提到生成代理等;这不是“直接本机/托管 C++/CLI”方法)。现在你基本上是在说这意味着“通过 COM 调用 .NET 时没有额外的惩罚,除了那里的惩罚”。这当然是一个真实的陈述,只是信息量不是很大:)
    • 初始化一般的 .NET 东西(CLR、JIT-Compiler 等)会有性能损失,初始化和使用 COM(读取注册表项、后期绑定)也会有类似的性能损失,编组等)。总而言之,这是相当可观的。但除此之外,你不会有任何问题。现在够清楚了吗 ;-) ?
    猜你喜欢
    • 2010-12-14
    • 2023-04-01
    • 1970-01-01
    • 2014-09-05
    • 2014-09-03
    • 2011-07-02
    • 1970-01-01
    • 2018-12-12
    • 2012-02-27
    相关资源
    最近更新 更多