C++ COM C# 混合模式互操作
我试图了解从非托管 C++ 调用 C# 库实现的选项。
我的顶级模块是一个非托管 C++ COM/ATL dll。我想集成现有托管 C# dll 的功能。我已经并且可以重新编译这两个库的源代码。
我通过阅读 MSDN 上的此概述等文章和 这个问题或许可以创建一个“混合模式”dll,允许本机 C++ 代码调用 C# 库。
我对这种方法有几个问题:
- 我该如何设置? 我可以简单地更改一些属性吗 在现有的 COM/ATL 项目上 允许使用 C# 模块吗?
- 这些混合模式调用将如何进行 性能与 COM 互操作不同 打电话?有没有共同的字符串 可用于防止的格式 之间的转换或深拷贝 模块?
- 如果创建了这个dll 混合模式还可以吗 以相同的方式接口/使用 它的 COM 客户端,或者他们是否需要 知道混合模式吗?
- 纳入 CLR 是否会带来重大影响? 加载此 COM 对象时的开销?
我是 Windows 开发新手,因此如果问题陈述中的任何内容需要澄清或更正,请发表评论。
提前致谢。
I'm trying to understand my options for calling a C# library implementation from unmanaged C++.
My top level module is an unmanaged C++ COM/ATL dll. I would like to integrate functionality of an existing managed C# dll. I have, and can recompile the source for both libraries.
I understand from reading articles like this overview on MSDN and this SO question that it might be possible to create a "mixed-mode" dll which allows the native C++ code to call into the C# library.
I have a couple of questions about this approach:
- How do I go about setting this up?
Can I simply change some properties
on the existing COM/ATL project to
allow use of the C# modules? - How will these mixed-mode calls
differ in performance from COM interop
calls? Is there a common string
format that may be used to prevent
conversion or deep copies between
the modules? - If this dll is created
mixed-mode, can it still be
interfaced/used in the same way by
its COM clients, or do they need to
be mixed mode aware? - Will inclusion of the CLR impose substantial
overhead when loading this COM object?
I'm new to Windows development, so please comment if anything in the question statement needs clarification or correction.
Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您完全控制该项目,那么更改此类设置不是问题,那么当然。您所需要做的就是为此项目启用
/clr
(在项目属性中,打开“常规”页面,并查找“公共语言运行时”支持)。现在,您可以根据需要在项目中使用托管句柄 (^
) 和其他 C++/CLI 位。所有用纯 C++ 编写的现有代码都应该继续工作(现在将尽可能编译为 MSIL,但其语义将保持不变)。混合模式调用会更快,因为它使用更快的调用约定,并且不会像 COM 互操作那样进行任何封送操作(您可以使用本质上兼容的类型,或者进行自己的显式转换)。
没有通用的字符串格式 - 问题是 System::String 既分配又拥有其缓冲区,并且还要求它是不可变的;所以你不能自己创建一个缓冲区,然后将其包装为
String
,或者创建一个String
,然后将其用作输出文本的缓冲区。它可以进行相同的接口,但如果它是通过本机入口点输入的,它将尝试将 CLR 加载到进程中,除非已经加载了 CLR。如果调用客户端在调用之前已经加载了 CLR(或者客户端本身是从托管代码调用的),那么您将获得已加载的 CLR,这可能与您的代码所需的 CLR 不同(例如客户端可能已加载 1.1,而您的代码需要 2.0)。
这取决于您对开销的定义。代码大小?运行时惩罚?内存占用?
无论如何,加载 CLR 意味着您获得所有 GC 和 JIT 机制。这些并不便宜。也就是说,如果您最终需要调用托管代码,则没有办法解决这个问题 - 您必须将 CLR 加载到某个进程中才能执行此操作。 COM Interop 和混合模式 C++/CLI 程序集之间的惩罚不会有所不同。
If you fully control that project, so changing such settings isn't an issue, then sure. All you need is to enable
/clr
for this project (In project properties, open the "General" page, and look for "Common Language Runtime" support). Now you can use managed handles (^
) and other C++/CLI bits in your project as needed. All existing code written in plain C++ should just keep working (it will be compiled to MSIL now, inasmuch as possible, but its semantics will remain unchanged).A mixed-mode call will be faster, because it uses faster calling conventions, and doesn't do any marshaling the way COM interop does (you either use types that are inherently compatible, or do your own explicit conversions).
There's no common string format - the problem is that
System::String
both allocates and owns its buffer, and also requires it to be immutable; so you can't create a buffer yourself and then wrap it asString
, or create aString
and then use it as a buffer to output text to.It can be interfaced the same, but if it's entered via an native entry point, it will try to load the CLR into the process, unless one is already loaded. If the calling client had already loaded CLR prior to the call (or the client was itself called from managed code), then you'll get the CLR that is already loaded, which may be different from the CLR that your code requires (e.g. client may have loaded 1.1, and your code needs 2.0).
It depends on what you define by overhead. Code size? Runtime penalties? Memory footprint?
In any case, loading the CLR means that you get all the GC and JIT machinery. Those aren't cheap. That said, if you need to call managed code ultimately anyways, there's no way around this - you will have to load CLR into some process to do this. The penalties aren't going to differ between COM Interop and mixed-mode C++/CLI assemblies.
我不能说太多细节,例如字符串问题,因为我从未积极使用过这种方法。
但是,您只需让 VS 向导为您创建一个代理,就可以轻松地从任何 C# 代码中使用任何 COM 接口,除了调用 COM 和 .NET 时总会有的性能开销之外,它没有任何性能开销。
另一方面,您只需将 C# 程序集的
ComVisibleAttribute
设置为 true(在 VS 中,它是项目属性中的一个简单复选框),然后编译器将自动为您创建 COM 接口。同样,没有额外的性能损失。哈!
I can't say much about the details like e.g. the string issues, since I never actively used this approach.
But you can easily consume any COM interface from any C# code by simply letting a VS wizard create a proxy for you, there is no performance overhead to it except the one that you always have when invoking COM and .NET.
The other direction, you just have to set your C# assemblies'
ComVisibleAttribute
to true (in VS it's a simple check box in the project properties), and then the compiler will automatically create COM interfaces for you. Again, there's no additional performance penalty.HTH!