我来自Delphi世界,静态导入DLL函数非常简单。您需要做的就是指定函数名称和模块,如下所示:
function GetTickCount : DWORD; stdcall; external 'Kernel32.dll';
为什么在C ++中我必须使用kernel32.lib
来导入函数?为什么我不能简单地告诉链接器像Delphi一样导入该函数?
我知道这对你们的老兄来说听起来很无趣,但是从Delphi进入C ++世界真的会让人感到困惑。
答案 0 :(得分:8)
C ++工具链需要几个步骤来完成Delphi可以一步完成的工作。在C ++中声明外部DLL函数时,没有(标准)方法来指示实际可以找到函数的命名DLL。就编译器而言,声明的函数只是extern
并且必须是一个可以通过链接器找到的定义。
要将命名函数连接到可以找到它的DLL,C ++工具链需要一个“导入库”,其中包含链接器知道如何处理的导入存根。当找到由导入存根定义的函数时,链接器会为相应DLL中的特定函数名创建DLL函数引用(如导入存根所示)。
在Delphi中,语言设计者允许程序员直接在源代码中指定相关的DLL。然后,Delphi编译器可以直接生成对外部DLL的引用,而无需使用导入存根步骤。
答案 1 :(得分:4)
您的问题实际上只是Microsoft C ++编译器(MSVC)的一个问题,它需要使用“导入库”作为将符号(即函数名称)绑定到函数的序列的中间步骤。 DLL。它本身不是C ++问题。这可能只是MSVC编译器的一个令人讨厌的怪癖,但我不太清楚这种方案的动机是否应该或可以改变。如果我没记错的话,C ++ Builder编译器也可以使用这种机制,模仿MSVC。
大多数其他编译器在链接和二进制接口方面与GCC的工作方式(GNU Compiler Collection)保持一致。那些不需要这个额外的“导入库”,您只需将有问题的DLL指定为与您的可执行文件链接的库的一部分。
顺便说一下,当谈到C ++链接器和Delphi链接器之间的差异时,你指出的这个问题只是冰山一角。它们在更深层次上有很大不同。 C ++标准几乎要求链接器相当简单(由于“单独的编译模型”),只是连接点,可以这么说,而在Delphi中,链接器与编译器的关系更紧密,并且通常更加智能(和快)。
答案 2 :(得分:1)