C++和 C# 互操作性:P/Invoke 与 C++/CLI
在寻找 C# 和 C++ 之间互操作的方法的过程中,我发现了这篇文章 解释了 P/Invoke。
我读了很多文章,声称 C++/CLI 并不完全是 C++,需要对原始 C++ 代码进行一些修改。
我想问当我有一些我想从 C# 对象使用的 C++ 对象(代码/数据)时,最佳方法是什么。
- 看起来为了使用 P/Invoke,我应该提供 C 风格的 API。这是真的吗?我的意思是,有没有办法像 SWIG 一样使用 P/Invoke 将 C++ 对象导出到 C#?或者,我是否必须使用 SWIG 才能达到此目的?
- 将 C++ 更改为 C++/CLI 有多难?与将 C++ 重写为 C# 相比,值得尝试吗? C++ 设计得很好,因此将其实现为 C# 并不是什么大事。
- (题外话)还有相反的方法吗?我的意思是,如果我想使用 C++ 中的 C# 代码,有什么办法可以做到吗?
In the course of finding a way to interoperate between C# and C++ I found this article that explains about P/Invoke.
And I read a lot of articles claiming that C++/CLI is not exact C++ and requires some effort to modify from original C++ code.
I want to ask what would be the optimal way when I have some C++ objects (code/data) that I want to use from C# objects.
- It looks like that in order to use P/Invoke, I should provide C style API. Is it true? I mean, is there a way to export C++ object to C# like SWIG with P/Invoke? Or, do I have to use SWIG for this purpose?
- How hard is it to change C++ to C++/CLI? Is it worth trying compared to rewrite the C++ to C#? The C++ is well designed, so implementing it to C# is not great deal.
- (Off the topic question) Is there the other way round? I mean, if I want to use C# code from C++, is there any way to do so?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我不建议将 C++ 库重写为 C++/CLI。相反,我会编写一个可以从 C# 调用的 C++/CLI 包装器。这将由一些
public ref class
类组成,每个类可能只管理本机类的一个实例。您的 C++/CLI 包装器只需“包含标头,链接到库”即可使用本机库。由于您已经编写了public ref class
类,因此您的 C# 代码仅添加 .NET 引用。在每个公共引用类中您所做的就是使用 C++ Interop(又名 It Just Works interop)来调用本机代码。如果您愿意,可以在使用时应用立面。I would not recommend rewritng your C++ library into C++/CLI. Instead, I would write a C++/CLI wrapper that you can call from C#. This would consist of some
public ref class
classes, each of which probably just manages an instance of the native class. Your C++/CLI wrapper just "include the header, link to the lib" to use the native library. Because you have writtenpublic ref class
classes, your C# code just adds a .NET reference. And all you do inside each public ref class is use C++ Interop (aka It Just Works interop) to call the native code. You can apply a facade while you're at it if you like.C++/CLI 语法很尴尬,但它确实允许您从 C++ 代码公开托管对象。如果您有一个大型 C++ API,并且可以将其中一些功能抽象为更简单的接口以供托管代码使用,那么这会很方便。我已经成功地完成了与 Matrox 视觉库等工具的集成,在其中我可以用 C++ 编写视觉分析代码,然后使用 C++/CLI 扩展来公开高级托管类。最痛苦的部分可能是字符串和数组的互操作,但字符串一直是痛苦的,即使在普通的 C++ 中也是如此。
C++/CLI 绝对可以使用任何 .NET 托管对象,但如果您使用任何指向托管内存的指针,则必须特别小心(在这种情况下,您需要使用固定。)如果我需要将指针传递给API,我通常更喜欢保持该内存非托管,然后创建托管包装类来操作非托管内存。
The C++/CLI syntax is awkward, but it does allow you to expose managed objects from C++ code. This can be convenient if you have a large C++ API and can abstract some of that functionality to a simpler interface for consumption by your managed code. I've done this successfully for integration with tools like the Matrox vision library, where I could write my vision analysis code in C++ and then use the C++/CLI extensions to expose high-level managed classes. The most painful part is probably string and array inter-op, but strings have always been painful, even in plain C++.
C++/CLI can definitely consume any .NET managed objects, but you have to take special care if you're using any pointers to managed memory (you'll need to use pinning in this case.) If I need to pass pointers to an API, I usually prefer to keep that memory unmanaged and then create managed wrapper classes for manipulating the unmanaged memory.
根据 Kate Gregory 的回答,要从 C++ 调用 C# 代码,使用 C++/CLI 是显而易见的方法,因为它使其变得极其简单和无缝。
Further to Kate Gregory's answer, to call C# code from C++, using C++/CLI is the obvious way to do it, as it makes it extremely simple and seamless.
将 C++ 本机类(作为指向实现的指针)包装到 C++/CLI 类中,然后调用 &通过在 .net 应用程序中“使用”这些基于 CLR 的类来使用它们。这是我推荐的方式。不要用 C++/CLI 重写现有的类。
Wrap your C++ native classes, as pointer to implementation, into C++/CLI classes, then call & use these CLR-based classes by 'using'ing them in your .net application. This is my recommended way. DO NOT REWRITE your existing classes in C++/CLI.