用 C++/CLI 包装非托管 C++ - 一种正确的方法

Posted

技术标签:

【中文标题】用 C++/CLI 包装非托管 C++ - 一种正确的方法【英文标题】:Wrapping unmanaged C++ with C++/CLI - a proper approach 【发布时间】:2011-01-10 00:07:33 【问题描述】:

如标题所述,我想让我的旧 C++ 库在托管 .NET 中工作。我想到了两种可能:

1) 我可能会尝试使用 /clr 编译库并尝试“It Just Works”的方法。

2) 我可能会为非托管库编写托管包装器。

首先,我想让我的库快速运行,就像它在非托管环境中一样。因此,我不确定第一种方法是否会导致性能大幅下降。但是,实施起来似乎更快(不是一个正确的词:-))(假设它对我有用)。

另一方面,我想到了在编写包装器时可能出现的一些问题(例如,如何包装一些 STL 集合(例如vector)?)我想编写一个与非托管 C++ 存在 - 这是一种合理的方法吗(例如,MyUnmanagedClassMyManagedClass 在同一个项目中,第二个包装另一个)?

你对那个问题有什么建议?哪种解决方案可以让我获得更好的结果代码性能?

提前感谢您的任何建议和线索!

干杯

【问题讨论】:

【参考方案1】:

首先,忘记托管 C++。使用 C++/CLI。

不同之处在于,Managed C++ 是 Microsoft 首次尝试将 C++ 扩展为与 .NET 一起使用,老实说,这真是太可怕了。

所以他们放弃了,转而设计了 C++/CLI,效果更好。

其次,如果您将其编译为 C++/CLI,则有效的 C++ 代码应该正常工作,因此这似乎是显而易见的方法。

当然,为了将 C++ 类型公开给 .NET 程序集,无论哪种方式,您都必须编写一些包装器。对于 STL 类型,您可以查看 Microsoft 的 STL/CLR 库。

但一般来说,只需添加 /cli 开关,将您的代码编译为 C++/CLI,然后添加您需要的包装器。您的代码没有任何理由会神奇地变慢或发生任何事情。

【讨论】:

编写“托管 C++” 我显然想到了 C++/CLI :-) - 现在已编辑,谢谢 :) 是的,把它们混在一起很常见。但这也可能导致混乱。 :) 对双下划线语法有如此多的仇恨:P 请记住,如果您的代码包含 any 本机类,那么它将不会在不受信任的模式下运行。如果您转身并想在 silverlight xap 中部署某些东西,则需要考虑一些事情。然后你必须使用/clr:pure,这意味着你必须重写所有内容。【参考方案2】:

我的做法是

    创建一个普通的非托管 .lib。确保作为 DLL 链接到标准运行时(如果 .lib 在程序集中,则需要)

    创建 C++/CLI 程序集。

    将 .lib 添加到程序集的链接中

    创建托管接口

    最小化跨托管/非托管调用的粒度。意思是,更喜欢获取大块数据(如数据结构),而不是使用来自托管端的非托管数据结构的接口。这是因为跨界调用很慢。

像 std::vector 这样的东西需要在 System.Collections 中手动包装——但是,“它只是工作”对于内置类型甚至函数指针都有好处。

其他问题。回调需要是 stdcall 才能转换为委托,并且发送到非托管回调的委托不持有引用(因此,安排在其他地方持有引用或在对象被 GC 时崩溃)。

【讨论】:

所以我假设第 4 步是使用 P/Invoke 方法? 没有。在 C++/CLI 中,您可以创建托管类和非托管类。没有 P/Invoke -- 两个类都在同一个程序集中 我实际上是在发表评论后不久才意识到的。这是 IJW(它只是工作)。我实际上是通过 Visual Studio 将非托管库和 CLI 库链接为同一解决方案的两个项目 -> 添加参考,就像在这个问题中一样:***.com/questions/18302784/… 是的,我必须为大多数数组、向量和其他编写转换复杂的类型。 MS Marshaling 库帮助很大:msdn.microsoft.com/en-us/library/vstudio/bb384865.aspx【参考方案3】:

如果你有很多非托管函数要包装,你应该考虑使用SWIG。它为您编写所有包装器和互操作代码,并预先编写了支持 std::vector、std::string、windows 类型等的 SWIG 接口文件。

如果你有兴趣,我有一个完整的例子来展示非托管 C++ DLL 函数。

【讨论】:

马克我想看一个完整的例子

以上是关于用 C++/CLI 包装非托管 C++ - 一种正确的方法的主要内容,如果未能解决你的问题,请参考以下文章

使用 C++/CLI 包装器将二维数组从 C# 传递到非托管 C++

非托管C++通过C++/CLI包装调用C# DLL

C# 使用 CLI 包装器调用非托管 C++

C++/CLI:返回对非托管对象的引用

尝试从 C++/CLI 调用非托管 C++ 时解决错误

在Visual Studio 2010中将Native / C ++ DLL链接到托管C ++ / CLI包装器