C ++ com c#混合模式互操作
-
20-09-2019 - |
题
我正在尝试了解我从不受管理的C ++调用C#库实现的选项。
我的顶级模块是一个非托管的C ++ COM/ATL DLL。我想整合现有的托管C#DLL的功能。我有,并且可以重新编译两个库的来源。
我从阅读文章中了解 此概述 在MSDN和 这个问题 可以创建一个“混合模式” DLL,该DLL允许本机C ++代码拨打C#库。
我对这种方法有几个问题:
- 我该如何进行设置?我可以简单地更改现有COM/ATL项目上的一些属性以允许使用C#模块吗?
- 这些混合模式调用的性能与COM Interop调用有何不同?是否可以使用通用的字符串格式来防止模块之间的转换或深拷贝?
- 如果创建此DLL混合模式,是否可以通过其COM客户端以相同的方式将其连接/使用,或者需要混合模式知道?
- 加载此COM对象时,包含CLR会施加大量的开销吗?
我是Windows开发的新手,因此,如果问题声明中的任何内容需要澄清或更正,请评论。
提前致谢。
解决方案
我该如何进行设置?我可以简单地更改现有COM/ATL项目上的一些属性以允许使用C#模块吗?
如果您完全控制该项目,因此更改此类设置不是问题,请肯定。您需要的只是启用 /clr
对于此项目(在项目属性中,打开“常规”页面,并寻找“通用语言运行时”支持)。现在您可以使用托管手柄(^
)和您项目中的其他C ++/CLI位。所有用普通C ++编写的现有代码都应继续工作(现在将尽可能地汇编给MSIL,但其语义将保持不变)。
这些混合模式调用的性能与COM Interop调用有何不同?是否可以使用通用的字符串格式来防止模块之间的转换或深拷贝?
混合模式调用将更快,因为它使用更快的呼叫约定,并且不会对COM Interop的操作方式进行任何宣传(您要么使用固有兼容的类型,要么进行自己的显式转换)。
没有常见的字符串格式 - 问题是 System::String
分配并拥有其缓冲区,还要求它是不变的。因此,您无法自己创建缓冲区,然后将其包裹为 String
, ,或创建一个 String
然后将其用作缓冲区以输出文本。
如果创建此DLL混合模式,是否可以通过其COM客户端以相同的方式将其连接/使用,或者需要混合模式知道?
它可以连接相同,但是如果它是通过本机入口点输入的,则它将尝试将CLR加载到该过程中,除非已经加载了CLR。如果调用客户端在呼叫之前已经加载了CLR(或者客户本身是从托管代码调用的),那么您将获得已加载的CLR,这可能与您的代码所需的CLR不同(例如客户端可能已加载1.1,您的代码需要2.0)。
加载此COM对象时,包含CLR会施加大量的开销吗?
这取决于您通过开销定义的内容。代码大小?运行时处罚?内存足迹?
无论如何,加载CLR意味着您可以获得所有GC和JIT机械。这些并不便宜。也就是说,如果您最终需要调用托管代码,无论如何都无法解决 - 您将 有 将CLR加载到某个过程中。 COM Interop和混合模式C ++/CLI组件之间的惩罚不会有所不同。
其他提示
我不能对诸如字符串问题之类的细节说太多,因为我从未积极使用这种方法。
但是,您可以通过简单地让vs向导为您创建代理,从而轻松地使用任何C#代码的COM接口,除了调用COM和.NET时始终具有的性能开销。
另一个方向,您只需要设置C#组件' ComVisibleAttribute
真实(在VS中,这是项目属性中的一个简单复选框),然后编译器将自动为您创建COM接口。同样,没有其他绩效罚款。
恩!