在使用库方面,C/C++/Objective-C 与 C# 相比如何?

2024-02-13

这个问题是基于之前的一个问题:C# 编译如何避免需要头文件? https://stackoverflow.com/questions/1917935/how-does-c-compilation-get-around-needing-header-files.

确认 C# 编译使用多次传递基本上回答了我最初的问题。此外,答案表明 C# 使用存储在程序集中的类型和方法签名元数据在编译时检查代码语法。

Q:C/C++/Objective-C 如何知道在运行时加载哪些在编译时链接的代码?为了将其与我熟悉的技术结合起来,C#/CLR 是如何做到这一点的?

如果我错了,请纠正我,但对于 C#/CLR,我的直观理解是在执行时检查某些路径是否有程序集,并且基本上所有代码都是在运行时动态加载和链接的。

编辑:更新为包含 C++ 和 Objective-C 以及 C。

Update:为了澄清,我真正好奇的是 C/C++/Objective-C 编译如何将源代码中的“外部定义”符号与该代码的实际实现相匹配,编译输出是什么,以及编译输出基本上是如何由微处理器执行,将控制无缝传递到库代码中(就指令指针而言)。我已经使用 CLR 虚拟机完成了此操作,但很想知道它在概念上如何在实际微处理器上的 C++/Objective-C 中工作。


链接器在 C/C++ 构建中解决外部依赖关系方面发挥着重要作用。 .NET 语言不使用链接器。

有两种外部依赖项,其实现可在链接时在作为链接器的输入提供的另一个 .obj 或 .lib 文件中使用。以及在另一个可执行模块中可用的那些。 Windows 中的 DLL。

链接器在链接时解析第一个,没有发生任何复杂的事情,因为链接器知道依赖项的地址。后一步高度依赖于平台。在 Windows 上,必须为链接器提供导入库。一个非常简单的文件,仅声明 DLL 的名称以及 DLL 中导出的定义的列表。链接器通过在代码中输入跳转并向外部依赖表添加一条记录来指示跳转位置,以便可以在运行时对其进行修补,从而解决依赖关系。 DLL 的加载和导入表的设置是由 Windows 加载程序在运行时完成的。这是整个过程的鸟瞰图,有很多无聊的细节可以让这一切尽快发生。

在托管代码中,所有这些都是在运行时由 JIT 编译器驱动完成的。它将 IL 转换为由程序执行驱动的机器代码。每当执行引用另一种类型的代码时,JIT 编译器就会立即采取行动,加载该类型并转换该类型的被调用方法。加载类型的副作用是加载包含该类型的程序集(如果之前未加载过)。

值得注意的是构建时可用的外部依赖项的差异。 C/C++ 编译器一次编译一个源文件,依赖关系由链接器解析。托管编译器通常将创建程序集的所有源文件作为输入,而不是一次编译一个。实际上支持单独的编译和链接(.netmodule 和 al.exe),但可用工具没有很好地支持,因此很少这样做。此外,它不支持扩展方法和分部类等功能。因此,托管编译器需要更多的系统资源来完成工作。可以在现代硬件上轻松使用。 C/C++ 的构建过程是在那些资源不可用的时代建立的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在使用库方面,C/C++/Objective-C 与 C# 相比如何? 的相关文章

随机推荐