2012-10-12 66 views
3

我來自Delphi世界,靜態導入DLL函數非常簡單。所有你需要做的就是指定函數名和這樣的模塊:Delphi鏈接器和C++鏈接器的區別

function GetTickCount : DWORD; stdcall; external 'Kernel32.dll'; 

在C++爲什麼要我以進口功能使用kernel32.lib?爲什麼我不能簡單地告訴鏈接器像Delphi那樣導入那個函數?

我知道這對你的manny聽起來可能不好,但是從Delphi出現在C++世界中真的會讓人困惑。

+1

這真的降到歷史。在C和C++世界中,這一直都是這樣做的。用於從DLL導入函數的.lib文件包含導入存根。 Delphi方法使編譯器生成這些存根。實際上,根據您接受的答案,它與序號與命名導入絕對無關。一些簡單的實驗可以證實這一點。 –

+0

這裏有一個類似的問題:http://stackoverflow.com/questions/6957061/why-do-i-need-to-link-a-lib-file-to-my-project事實上,它幾乎是一個重複的這一個 –

回答

6

C++工具鏈需要幾個步驟來完成Delphi可以一步完成的工作。當在C++中聲明一個外部DLL函數時,沒有(標準的)方法來指示函數實際可以找到哪個命名的DLL。就編譯器而言,聲明的函數只是extern,並且必須有一個定義可以在鏈接器的某處找到。

要將命名的函數連接到可以找到它的DLL,C++工具鏈需要一個包含導入存根的「導入庫」,鏈接器知道該如何處理。當找到由導入存根定義的函數時,鏈接器爲相應DLL中的特定函數名稱(如導入存根指示)創建DLL函數引用。

在Delphi中,語言設計者允許程序員直接在源代碼中指定關聯的DLL。 Delphi編譯器可以直接生成對外部DLL的引用,而無需使用導入存根步驟。

+0

我想C++真的需要在這方面的更新:)。謝謝你的啓發。 – opc0de

+0

@ opc0de:作爲一個獨立於平臺的語言標準,C++本身不能做太多工作。德爾福一直都是平臺特定的(afair Linux和Windows)。 –

+0

@phresnel看看免費的pascal它是跨平臺的 – opc0de

4

你的問題實際上只是與Microsoft C++編譯器(MSVC)有關,它需要使用「導入庫」作爲將符號(即函數名)綁定到函數序號的中間步驟該DLL。它本身不是C++問題。這可以說是MSVC編譯器的一個令人討厭的怪癖,但我對這種方案是否應該或可能被更改的動機還沒有足夠的瞭解。如果我沒有記錯的話,C++ Builder編譯器也可以用這種機制來模仿MSVC。

大多數其他編譯器遵循GCC工作方式(GNU編譯器集合)的鏈接和二進制接口。而那些不需要這個額外的「導入庫」,你只需將問題中的DLL指定爲庫的一部分來鏈接你的可執行文件。

順便說一下,當涉及到C++鏈接器和Delphi鏈接器之間的區別時,您指出的這個問題只是冰山一角。他們在更深的方面是非常不同的。 C++標準幾乎要求鏈接器相當簡單(由於「獨立編譯模型」),只需連接點即可,可以這麼說,而Delphi鏈接器與編譯器密切相關,並且通常更智能(並且更快)。

+0

我用MinGW使用Qt,我仍然需要鏈接那種方式。也許有一種方法,我不知道它。我會做一些研究。謝謝 – opc0de

+1

@Mikael你有任何文件來支持它嗎?我使用gcc/g ++的Windows端口的經驗是,您仍然需要使用MS格式的.lib導入庫。 –

+2

@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。 –