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

时间:2011-01-10 00:07:33

标签: .net c++ unmanaged wrapper managed

如标题中所述,我希望我的旧C ++库在托管.NET中运行。我想到了两种可能性:

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

2)我可能会将托管包装器写入非托管库。

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

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

你会在那个问题上提出什​​么建议?哪种解决方案能够让我更好地了解生成的代码?

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

干杯

3 个答案:

答案 0 :(得分:6)

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

不同之处在于Managed C ++是微软首次尝试将C ++扩展到与.NET协同工作,老实说,这种做法各种各样可怕。

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

其次,如果您将其编译为C ++ / CLI,那么有效的C ++代码只能正常工作,所以这看起来似乎是显而易见的方法。

当然,为了将您的C ++类型公开给.NET程序集,您将不得不以任何方式编写一些包装器。对于STL类型,您可以查看Microsoft的STL/CLR库。

但一般来说,只需添加/ cli开关,将代码编译为C ++ / CLI,然后添加所需的包装器。没有理由为什么你的代码会神奇地变得更慢或什么。

答案 1 :(得分:3)

我的方式是

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

  2. 创建C ++ / CLI程序集。

  3. 将.lib添加到类似于程序集的链接

  4. 创建托管界面

  5. 最大限度地减少托管/非托管的调用粒度。这意味着,更喜欢获取大块数据(如数据结构),而不是使用来自托管端的非托管数据结构的接口。这是因为跨越边界的呼叫很慢。

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

    其他陷阱。回调需要stdcall转换为委托,并且发送到非托管回调的delgates不保存引用(因此,安排在其他地方保留引用或在对象为GC时崩溃)。

答案 2 :(得分:1)

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

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