1

我发现有一堆项目(SharpDX等)正在编译以允许CLR“管理”本机代码,然后直接从例如c#调用该本机代码(c ++函数)。

我正在尝试弄清楚这是如何工作的……如果你们中的任何人都知道,那就太好了。

到目前为止,我所看到的是,我可以将 C# 项目中的引用添加到“CLR 兼容”C++ 库中,就像任何其他 c# 库(无需反射)一样,将其添加为:“使用 myCppLibrary”,然后只是调用任何可用的方法。

当我去查看我刚刚添加的引用中可用的函数时,似乎我可以从 c# 访问在 C++ 库的头文件 (.h) 文件中声明为 PUBLIC 的任何内容,因为它们被自动转换为 c# 代码编译器。

所以实际上发生的事情是:

我在我的 c++ 库的头文件 (.h) 中声明了公共方法/变量。我编译它们检查 CLR 管理在库的属性选项卡中是否可用。(我正在使用 Visual Studio 2012)编译器为每个头文件 (.h) 生成 c# 类,其中包含任何公共方法/属性。

但我不明白的是,当我打电话时,可以说,“myCppLibrary”中的 giveNumber() 函数......该函数的实现在哪里执行?

CLR 会自动与 c++ 本机代码进行交互还是实际发生了什么?

4

2 回答 2

3

不太确定我完全理解你所看到的。但是您看到错误的副作用的可能性很高。C++/CLI 编译器能够将任何与 C++03 兼容的本机 C++ 代码编译成 IL。IL 和抖动都足够灵活以支持这一点。就像 C# 编译器生成的 IL 一样,这种 IL 将在运行时转换为机器代码,并以完全相同的方式进行优化。

然而,这并不能使它成为托管代码。此代码创建的任何对象仍然是在非托管内存中分配的本机对象,就像本机 C++ 编译器所做的那样。垃圾收集器完全没有注意到它们。

那么错误是允许将该代码翻译成IL。您错过了 C++ 代码生成器在编译时花费的额外时间来寻找最佳优化的机器代码。抖动也得到了优化,但它不能做得很好,必须在时间限制下运行。当然,您将在运行时承担抖动开销。

本机结构和类将在程序集元数据中可见。但它们只是不透明的值类型,C# 程序无法访问它们的成员。您不能直接从 C# 调用此类本机类的方法。为了可用,C++/CLI 程序必须使用valueref上下文关键字声明类型。像ref class一样,完全等同于 C# 类。

因此,将本机代码编译为机器代码非常重要,就像常规 C++ 编译器所做的那样。你可以通过编译一个没有/clr 的.cpp 源文件来实现。或者通过使用#pragma unmanaged 和#pragma managed 包装此类代码,在机器代码和IL 生成之间来回切换编译器。您从 C++/CLI 获得的附加值是 ref 类中的方法可以直接使用本机代码,而无需像 pinvoke 那样在 C# 中必须经历的那种麻烦。并且使用本机 C++ 类,这是您在 C# 中完全无法做到的。

于 2013-05-30T21:07:36.337 回答
2

当您在 C++ 中启用 CLR 时,编译器会将 C++ 代码编译为 IL 而不是本机代码。在这种情况下,被称为C++/CLI的 C++ 增加了各种功能,以允许它使用垃圾收集器,可以很好地控制垃圾收集的内存是否被固定以避免移动等。

编写 C++/CLI 通常是一项专业任务,需要同时了解 C++ 和 C#(可能存在一些细微的差异和陷阱)。通常建议将其用于本机代码和托管代码之间的接口,但它可用于将整个库制作成 .net。

于 2013-05-30T20:30:23.293 回答