我很难了解托管C 如何工作和编译。
在.NET框架中,您可以在C#/vb/f#/..等中开发代码。所有这些语言将被编译为类似于Java字节码的相同常见中间语言(CIL)。从理论上讲,CIL可以安装在任何平台上(单声道使其实用)。在Windows上,CLR将CIL编译为本机代码Just-time(JIT),并且一切顺利且良好。
现在,托管C 如何被编译?它是否编译为CIL代码并等待CLR使用JIT运行它?我认为不是,因为托管的C 可以使用标准的C 代码(未编译为CIL)。此外,它如何使用.NET组件(CIL)?
我感谢任何帮助。谢谢
编辑:
我已经看到了这个答案。它指出,在C /CLI中,托管代码将被编译到MSIL,您可以选择将未托管的代码编译为本机代码或MSIL。因此,我现在了解对.NET组件的呼吁。
无论如何,我仍然不明白,如果将未托管的代码汇编为本机代码,则C 未托管代码如何使用同一汇编中的托管代码运行。有什么想法吗?
这是一个很大的主题,具有非常坚韧的实现细节。很难解决所有这些问题,但是这个问题存在一些误解。让我们解决这些问题,可能有助于到达下一阶段。
此外,它如何使用.NET组件(CIL)?
不仅是CIL,链接器还会产生A 混合模式组装。包含.NET元数据 MSIL 和本机代码。实际上,就OS加载程序而言,正常的是可执行文件中的本机代码。与天然C 编译器产生的类型没有什么不同。它像纯本机可执行的图像一样被加载和重新定位。是.NET元数据 MSIL是奇数。对于装载机来说,它看起来像大量数据,根本不会触及它。只有CLR才能。
...使用标准C 代码(未汇编为CIL)
不太准确,本机C 代码可以编译到MSIL 或机器代码。您得到的取决于/CLR编译选项是否已使用或在功能级别生效的#pragma管理。CIL与Java JVM中使用的字节码相提并论。它更强大,可以支持任何符合C 03的本机C 代码。有时,您是故意使用反向PINVOKE(本机代码调用托管代码)的。有时,这是偶然完成的,完全过多的本机C 代码会被编译为MSIL。抖动产生的机器代码不是最佳的(它在时间限制下优化),也不以任何方式管理。它是不可验证的,也不会得到垃圾收集器的爱。
CIL的最佳心理图像是在前端(Parser)和后端(代码生成器和优化器)之间使用的任何天然C 编译器中使用的中间表示。通常是无形的实现细节,但是当您使用使用LLVM的C 编译器时(就像Clang一样)时会变得更加明显。.NET即时编译器在运行时执行LLVM在编译时的作用。
当托管代码调用本机代码(或相反的方式)时,大多数程序员都具有巨大模式开关的心理图像。这根本不准确。您可能需要看这篇文章,显示C 编译器的后端和抖动产生的机器代码之间的差异。关键是它几乎是相同的,这是确保托管代码与本机代码具有竞争力的重要功能。有助于阐明托管代码调用本机代码或相反方式的方式并不是那么特别。
另一个误解是托管代码自动更安全。不太正确,像C#这样的语言让您像使用C 一样在堆栈上派对,并在堆栈上乱涂乱码,并且您可以轻松地以这种方式折磨内存。它只是更好的分区,它迫使您使用unsafe
关键字对其进行明确的划分。在C /CLI上没有任何限制,任何事情都会发生。
托管代码和本机代码之间的本质区别是抖动编译MSIL时生成的数据结构。您不会从本机编译器中获得的额外数据。该数据是垃圾收集器所需的,它告诉它如何查找对象根。在这篇文章中有关该数据的更多信息。必须符合该数据并允许GC完成其工作是使托管代码在运行时稍慢的原因。
已否定了C 。今天要编写本机C 和管理代码,您需要使用C CLI。它符合CLR,并且可以运行其他.NET组件。您也可以使用本机呼叫,它们非常适合本机代码和.NET代码之间的互操作性要调用.NET汇编在您的项目中添加引用到该组件并添加您的代码:
using namespace System;