代码之家  ›  专栏  ›  技术社区  ›  G-Wiz RameshVel

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

  •  1
  • G-Wiz RameshVel  · 技术社区  · 15 年前

    How does C# compilation get around needing header files? .

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

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

    编辑:更新到包括C++和ObjuleC与C。

    澄清一下,我真正感兴趣的是C/C++/Objective-C编译如何将源代码中的“外部定义”符号与代码的实际实现相匹配,编译输出是什么,基本上,微处理器是如何执行编译输出的,从而将控制无缝地传递到库代码中(以指令指针的形式)。我已经用CLR虚拟机实现了这一点,但我很想知道在实际的微处理器上,它在C++/Objective-C中是如何工作的。

    4 回复  |  直到 7 年前
        1
  •  7
  •   Hans Passant    15 年前

    链接器在C/C++构建中起着重要作用,以解决外部依赖关系。NET语言不使用链接器。

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

    值得注意的是,对于构建时可用的外部依赖项,也存在差异。C/C++编译器一次编译一个源文件,依赖项由链接器解析。托管编译器通常将创建程序集的所有源文件作为输入,而不是一次编译一个。事实上,单独编译和链接是受支持的(.netmodule和al.exe),但可用的工具不支持单独编译和链接,因此很少进行单独编译和链接。此外,它不能支持扩展方法和分部类等特性。因此,托管编译器需要更多的系统资源才能完成任务。在现代硬件上随时可用。C/C++的构建过程是在这些资源不可用的时代建立的。

        2
  •  2
  •   caf    15 年前

    符号分辨率 . 在一般情况下,它的工作原理是这样的(我试图让它保持操作系统的中立性):

    1. 象征 未在源文件本身中定义的(即函数或外部变量名)会导致占位符留在编译后的机器语言代码中,无论它们在何处被引用。未知符号也会添加到目标文件的列表中-在编译结束时,此列表包含 分辨的符号 在对象文件中,与添加的所有占位符在对象文件中的位置交叉引用。每个对象文件还包含一个符号列表 出口

    2. 静态链接 . 这也发生在编译时。在静态链接过程中,在第一步中创建的所有对象文件和任何静态库文件(只是一种特殊的对象文件)都被合并到一个可执行文件中。静态链接器传递每个对象文件和静态库输出的符号,并构建输出符号(及其值)的完整列表。然后,它将遍历每个对象文件中未解析的符号,并在主列表中找到该符号的位置,将所有占位符替换为该符号的实际值。对于在此过程结束时仍然未解析的任何符号,链接器将查看它所知道的所有动态库导出的符号列表。它构建所需的动态库列表,并将其存储在可执行文件中。如果仍然没有找到任何符号,链接过程将失败。

    3. 第三步是 动态链接 ,这在运行时发生。动态链接器加载可执行文件中包含的列表中的动态库,并用动态库中的相应值替换剩余未解析符号的占位符。这可以在可执行文件加载后但在运行之前“急切地”完成,也可以在首次访问未解析符号时按需“延迟”完成。

        3
  •  1
  •   anon anon    15 年前

        4
  •  0
  •   Peter Mortensen icecrime    15 年前

    按库,您指的是DLL,对吗?