了解托管C++

Eve*_*one 4 .net c++ clr cil managed

我无法理解托管C++如何工作和编译.

在.NET Framework中,您可以使用C#/ VB/F#/ ..等开发代码.并且所有这些语言都将编译为与Java字节码类似的相同公共中间语言(CIL).从理论上讲,CIL可以安装在任何平台上(Mono使其实用).在Windows上,CLR将CIL编译为本机代码Just-In-Time(JIT),一切运行顺利,好用.

现在,Managed C++如何编译?它是否编译为CIL代码并等待CLR使用JIT运行它?我认为不是,因为托管C++可以使用标准C++代码(不编译为CIL).此外,它如何使用.NET程序集(CIL)?

我将不胜感激任何帮助.谢谢

编辑:

我看到了这个答案.它指出,在C++/CLI中,托管代码被编译为MSIL,您可以选择将非托管代码编译为本机代码或MSIL.因此,我现在明白如何调用.NET程序集.

无论如何,如果将非托管代码编译为本机代码,我仍然不明白如何在同一程序集中使用托管代码运行C++非托管代码.有任何想法吗?

Han*_*ant 7

这是一个非常坚韧的实现细节的重要主题.很难解决这些问题,但问题中存在一些误解.让我们来解决这些问题,可能有助于进入下一阶段.

此外,它如何使用.NET程序集(CIL)?

不仅仅是CIL,链接器还会生成混合模式程序集.包含.NET元数据+ msil 本机代码.实际上,就OS加载器而言,可执行文件中的本机代码是正常的.与本机C++编译器生成的类型没有什么不同.它像纯粹的本机可执行映像一样被加载和重定位.这是一个古怪的.NET元数据+ msil.对于加载器来说,它看起来只是一大块数据,根本不会触及它.只有CLR才有.

...使用标准C++代码(未编译为CIL)

不太准确,可以将本机C++代码编译为msil 机器代码.您获得的内容取决于是使用了/ clr编译选项还是在函数级别生效的#pragma managed.CIL没有将它与Java JVM中使用的字节码进行比较.它功能更强大,可以支持任何符合C++ 03的本机C++代码.有时您这样做是为了利用反向pinvoke(本机代码调用托管代码).有时它是偶然完成的,并且完全过多的本机C++代码被编译为msil.由抖动产生的机器代码不是最佳的(它在时间限制下优化)并且不以任何方式管理.它不可验证,也不会得到垃圾收集器的爱.

CIL的最佳心理图像是在前端(解析器)和后端(代码生成器和优化器)之间的任何本机C++编译器中使用的中间表示.通常是一个不可见的实现细节,但在使用使用LLVM的C++编译器时会更加明显(如Clang一样)..NET即时编译器在运行时执行LLVM在编译时执行的操作.


当托管代码调用本机代码(或其他方式)时,大多数程序员都会抛出巨型模式切换的心理图像.这根本不准确.您可能想看一下这篇文章,展示C++编译器后端产生的机器代码与抖动之间的区别.关键是几乎相同,这是确保托管代码与本机代码竞争的基本功能.有助于澄清托管代码调用本机代码的方式,或者反过来说,并不是那么特别.

另一个误解是托管代码自动更安全.不太正确,像C#这样的语言让你可以像使用C++一样使用指针和乱涂乱画,你也可以像这样轻松地破坏内存.它只是更好地分区,它迫使你用unsafe关键字明确它.在C++/CLI上没有这样的限制,任何事情都有.

托管代码和本机代码之间的本质区别是抖动在编译msil时生成的数据结构.您无法从本机编译器获得的额外数据.垃圾收集器需要该数据,它告诉它如何找回对象根.更多关于这篇文章中的数据.必须符合该数据并允许GC完成其工作才能使托管代码在运行时稍慢.