我來自Delphi世界,靜態導入DLL函數非常簡單。所有你需要做的就是指定函數名和這樣的模塊:Delphi鏈接器和C++鏈接器的區別
function GetTickCount : DWORD; stdcall; external 'Kernel32.dll';
在C++爲什麼要我以進口功能使用kernel32.lib
?爲什麼我不能簡單地告訴鏈接器像Delphi那樣導入那個函數?
我知道這對你的manny聽起來可能不好,但是從Delphi出現在C++世界中真的會讓人困惑。
我來自Delphi世界,靜態導入DLL函數非常簡單。所有你需要做的就是指定函數名和這樣的模塊:Delphi鏈接器和C++鏈接器的區別
function GetTickCount : DWORD; stdcall; external 'Kernel32.dll';
在C++爲什麼要我以進口功能使用kernel32.lib
?爲什麼我不能簡單地告訴鏈接器像Delphi那樣導入那個函數?
我知道這對你的manny聽起來可能不好,但是從Delphi出現在C++世界中真的會讓人困惑。
C++工具鏈需要幾個步驟來完成Delphi可以一步完成的工作。當在C++中聲明一個外部DLL函數時,沒有(標準的)方法來指示函數實際可以找到哪個命名的DLL。就編譯器而言,聲明的函數只是extern
,並且必須有一個定義可以在鏈接器的某處找到。
要將命名的函數連接到可以找到它的DLL,C++工具鏈需要一個包含導入存根的「導入庫」,鏈接器知道該如何處理。當找到由導入存根定義的函數時,鏈接器爲相應DLL中的特定函數名稱(如導入存根指示)創建DLL函數引用。
在Delphi中,語言設計者允許程序員直接在源代碼中指定關聯的DLL。 Delphi編譯器可以直接生成對外部DLL的引用,而無需使用導入存根步驟。
你的問題實際上只是與Microsoft C++編譯器(MSVC)有關,它需要使用「導入庫」作爲將符號(即函數名)綁定到函數序號的中間步驟該DLL。它本身不是C++問題。這可以說是MSVC編譯器的一個令人討厭的怪癖,但我對這種方案是否應該或可能被更改的動機還沒有足夠的瞭解。如果我沒有記錯的話,C++ Builder編譯器也可以用這種機制來模仿MSVC。
大多數其他編譯器遵循GCC工作方式(GNU編譯器集合)的鏈接和二進制接口。而那些不需要這個額外的「導入庫」,你只需將問題中的DLL指定爲庫的一部分來鏈接你的可執行文件。
順便說一下,當涉及到C++鏈接器和Delphi鏈接器之間的區別時,您指出的這個問題只是冰山一角。他們在更深的方面是非常不同的。 C++標準幾乎要求鏈接器相當簡單(由於「獨立編譯模型」),只需連接點即可,可以這麼說,而Delphi鏈接器與編譯器密切相關,並且通常更智能(並且更快)。
我用MinGW使用Qt,我仍然需要鏈接那種方式。也許有一種方法,我不知道它。我會做一些研究。謝謝 – opc0de
@Mikael你有任何文件來支持它嗎?我使用gcc/g ++的Windows端口的經驗是,您仍然需要使用MS格式的.lib導入庫。 –
@DavidHeffernan在MinGW中,當處理MS生成的DLL時,您只需要MS樣式機制,反之亦然(爲MinGW DLL生成MSVC友好的庫)。有像dlltool和reimp這樣的工具可以完成導入庫的轉換/創建。在任何情況下,鏈接不使用相同C++ ABI的DLL和EXE是一個非常糟糕的主意。使用C兼容DLL或GCC/ICC/Clang的C++ DLL,鏈接器可以在沒有導入庫的情況下處理它們(請參閱http://www.mingw.org/wiki/CreateImportLibraries)。 GCC處理像類Unix操作系統中的共享對象那樣的DLL。 –
我剛剛提交了以下的功能要求QC:
QC#109493: Add a compiler extension to import DLL functions without needing an import .lib file
您是否將QC報告置於現場測試版本之下? –
不,我把它歸檔到XE3 RTM下,我不知道爲什麼它被標記爲私有。 –
這真的降到歷史。在C和C++世界中,這一直都是這樣做的。用於從DLL導入函數的.lib文件包含導入存根。 Delphi方法使編譯器生成這些存根。實際上,根據您接受的答案,它與序號與命名導入絕對無關。一些簡單的實驗可以證實這一點。 –
這裏有一個類似的問題:http://stackoverflow.com/questions/6957061/why-do-i-need-to-link-a-lib-file-to-my-project事實上,它幾乎是一個重複的這一個 –