__declspec(dllimport)的小祕密(轉)

昨天和同事使用一個dll(lib+dll)的時候,發現他在引用頭文件是,並無使用__declspec(dllimport),可是程序徹底運行正常,不明覺厲下,去網上翻了下資料,原來是連接器的緣由,這裏貼一個轉帖,已經寫得很清楚了。函數

 

鄧立波 深圳,2008-6spa

做者聯繫方式:blog

email:    libodeng@gmail.comget

msn:     libodeng@gmail.com編譯器

 

 

        按照MSDN說明,當連接dll的導出函數時,只須要包含頭文件和lib,__declspec(dllimport)修飾符不是必須的,但加上該修飾能使導出函數的調用效率更高。那麼,究竟緣由是什麼?編譯

假設dll導出了一個函數:
extern "C" __declspec(dllexport) void fun();
若是程序中聲明不加__declspec(dllimport),查看調用fun()函數的彙編代碼:
    004010AD   call        fun (004010d8)
其中fun被定義爲一個標號(label),以下:
fun:
    004010D8   jmp         dword ptr [__imp__fun (0040e0e8)]
上面的符號__imp__fun指向的地址爲fun()函數在exe中的導入節。效率

當聲明加上__declspec(dllimport)後,查看調用fun()函數的彙編代碼:
    004010AB   call        dword ptr [__imp__fun (0040e0e8)]email

 

從上面能夠看出,加上__declspec(dllimport),編譯器連接dll將省略一條jmp語句。
這是由於:import

1。若是導出函數的聲明沒有用__declspec(dllimport) 修飾的話,編譯器並不知道這個函數是由DLL導出的,因此編譯器就把這個函數看成普通的外部引用來對待,產生一個外部引用的符號等着連接器解析。當連接器工做的時候,它是不能修改編譯器生成的結果,因此會將該符號解析爲對相應函數調入節的間接調用。引用

2。若是導出函數的聲明用__declspec(dllimport) 修飾的話,編譯器一開始就知道這個函數是DLL導出函數,直接編譯成對調入節的調用。

 

原文:http://libo.deng.blog.163.com/blog/static/40157422200851124138373/

相關文章
相關標籤/搜索