2014-07-10 24 views
2

我總是想知道__declspec(dllimport)的真實用例是什麼。我知道構建共享庫需要使用__declspec(dllexport)導出其符號,然後庫的用戶使用這些符號作爲__declspec(dllimport)VisualStudio中的dllimport使用案例

然後,你應該建立一個特殊的定義,使dllexport共享庫,如果沒有設置標誌,符號被定義爲dllimport

但是,我從來沒有使用dllimport,它只是工作。

我有兩個項目:

ImportExport

設有一個小的Util類,這是建立與出口定義

Util.h:

#ifndef _UTIL_H_ 
#define _UTIL_H_ 

#if defined(EXPORTING) 
# define EXPORT __declspec(dllexport) 
#else 
# define EXPORT // I should use __declspec(dllimport) but client will try out 
#endif 

class EXPORT Util { 
public: 
    static void test(); 
}; 

#endif // !_UTIL_H_ 

然後文件Util.cpp:

#include <iostream> 

#include "Util.h" 

void Util::test() 
{ 
    std::cout << "Testing..." << std::endl; 
} 

沒什麼太複雜的,正如你所看到的,當用戶使用這個文件時,EXPORT根本就不會被定義(它應該被定義爲dllimport)。

客戶端EXE

Main.cpp的:

#include <Util.h> 

int main(void) 
{ 
    Util::test(); 

    return 0; 
} 

鏈接ImportExport.lib沒有任何限定設置,只是工作。沒有未定義的參考。

我想知道爲什麼是dllimport的用例?它是爲了向後兼容性而存在嗎?

注意:所有提交的代碼都是在VisualStudio 2012 Express上測試的。

+0

示例:爲您的c#應用程序創建一個opencl包裝器2.0。 –

+0

http://blogs.msdn.com/b/oldnewthing/archive/2006/07/27/680250.aspx,至少從「調用導入的函數,天真的方式」開始 –

回答

4

Raymond Chen詳細描述了dll導入機制this series;總結起來,dllimport的功能本質上是一個性能優化。

如果您不將函數標記爲dllimport,則編譯器和鏈接器will treat it as a normal function使用「靜態」函數調用將其解析爲在導入庫中找到的存根。存根實際上必須從IAT中獲取導入函數的地址並在那裏執行一個jmp(即它必須以某種方式將編譯器生成的直接調用轉換爲間接調用),所以在這兩步中會有一些性能損失處理。

dllimport,而是通過編譯階段通過IAT通知編譯器it has to generate code for an indirect call。這樣可以減少間接尋址,並允許編譯器將(在本地)緩存目標函數地址。

請注意,as MSDN says,您只能省略dllimport的功能;對於數據來說它總是有必要的,因爲鏈接器沒有可用的機制來重寫直接訪問由編譯器生成的變量的間接訪問。

(這一切都是在「經典」的接頭時間尤爲重要;如今,隨着鏈接時代碼生成啓用,所有這些問題可以通過簡單地讓連接器完全生成函數各地工作調用/數據存取)

+0

好的,謝謝。我將開始添加dllimport :-)。 – markand