如何将 COM 对象的 C# 引用传递给 C++ DLL
Posted
技术标签:
【中文标题】如何将 COM 对象的 C# 引用传递给 C++ DLL【英文标题】:How to pass a C# Reference to COM Object to a C++ DLL 【发布时间】:2009-08-12 19:27:19 【问题描述】:我正在编写一个 Visual Studio 插件来处理 C++ 代码,并认为 COM 互操作让我的速度慢了很多。因此,我想将 COM 对象的 C# 引用传递给一个小的 C++ DLL,让 DLL 执行必要的计算并返回一个字符串。
我会将CodeFunction2 对象传递给 DLL 并获取返回方法信息的 XML 字符串。
虽然欢迎您质疑我是否真的需要这个来提高性能,但如果您在 COM 互操作中为数千种方法调用十几个成员变量,那么在托管代码和非托管代码之间切换似乎会占用太多时间。
如何格式化 C++ DLL 的参数?我一般没有从托管代码调用非托管代码的经验,但我需要回答的主要问题是如何格式化调用。
【问题讨论】:
【参考方案1】:也许您应该改为编写托管 C++ dll(使用 /clr 开关),然后您可以直接将托管对象传递到 C++ dll 并执行您喜欢的任何 COM 魔术,而不必担心在 dll 之间传递它们。
【讨论】:
后端和.NET有区别吗?这不会还有COM互操作问题吗?我是否感到困惑,或者这不仅仅是改变我想要做的语法。问题是跨托管/非托管代码对 CodeFunction2 对象的 COM 字段的多次访问正在减慢一切。托管 C++ 如何绕过这一点? 托管 C++ 同时存在于两个世界中。您使用“^”作为指向托管对象的指针,使用“*”作为指向典型 C++ 对象的指针。一个“托管”函数可以直接引用 .NET 对象,然后完全不受管理地处理下一组 COM 行,然后返回处理 .NET 对象。在托管 C++ 中,混合和匹配几乎是一件轻而易举的事。 你可以做一些非常简单的事情,比如写一个循环。在循环内部,您只使用标准 C++ 代码。将不会使用 .NET 对象,因此不会进行上下文切换。在循环之前和之后,您可以随意引用 .NET 对象。同样,在 C++ 中混合托管和非托管代码非常容易,只是在您编写时会意外发生。如果您没有显式引用 .NET 对象,则它不会进行任何托管/非托管上下文切换。 (事实上,根本没有任何上下文切换。您必须为转换显式编写代码,或使用 .NET 函数。) 您可以将 .NET 对象从 C# 传递到 C++,就像调用另一个 C# dll 一样。在 C++ 函数内部,您可以编写任何您喜欢的代码。 C++ 的混合模式并不关心您何时使用或使用什么。您可以一次将托管对象的数据转换为非托管数据,然后在调用 COM 期间重复使用该数据十亿次,而无需触及托管代码。您可以使用 System.Runtime.InteropServices.Marshal 中的函数从 .NET 对象中获取 COM 指针。它们会为您提供 IntPtr 值,这些值可以转换为原生 C++ COM 指针(因为它们就是这样)。 感谢所有帮助。肯定回答了我的问题【参考方案2】:如果你真的认为 C#/COM 互操作会拖慢你的速度,为什么不用 C++ 编写你的 VS 插件呢?这将避免必须从 C# 插件 dll 传递到 C++ dll 来处理 COM 互操作 - 在同一个地方完成所有操作。
【讨论】:
不错的主意,但有相当多的 GUI 工作。坦率地说,我主要不想重写这件事,所以我打算用 C# 编写前端,用托管 C++ 编写后端。但你是对的,如果我不得不重新来过,我可能会一直使用托管 C++。如果您说只使用本机 C++,那么问题是我使用了很多 Visual Studio 可扩展性的东西,而在 VS 2008 中,这似乎在托管代码中运行良好。【参考方案3】:正如其他人所指出的,托管 C++ 将是一个好主意,因为它使互操作变得轻而易举。如果您决定使用它,而不是托管 C++,我建议使用 C++/CLI,它在功能上是相同的,但它更新并且语法更简洁(它旨在取代托管 C++)。 (在托管 C++ 中,你有 __gc
之类的东西,这些东西很丑)。
Here 是一个很好的关于互操作场景的教程。
【讨论】:
以上是关于如何将 COM 对象的 C# 引用传递给 C++ DLL的主要内容,如果未能解决你的问题,请参考以下文章