• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            yehao's Blog

            DLL編程總結

            1)創建DLL

            創建DLL的時候,頭文件里在輸出變量,函數,類之前使用__declspec(dllexport)修飾符號。當VC編譯器看到變量,函數或者類之前的這個修改符的時候,它就將某些附加信息嵌入產生的.obj文件中。當鏈接DLL的所有.obj文件時,鏈接程序要查找關于輸出變量,函數或類的信息,并自動生成一個.lib文件,它包含一個DLL輸出的符號列表。如果要鏈接引用該DLL的輸出符號的任何可執行模塊,該.lib文件是必不可少的。(DLL工程需要定義MYMATHLIB_EXPORTS宏)

            MyMathLib.h

            1. #ifdef MYMATHLIB_EXPORTS   
            2. #define MYMATHLIB_API __declspec(dllexport)   
            3. #else   
            4. #define MYMATHLIB_API __declspec(dllimport)   
            5. #endif   
            6.   
            7. int MYMATHLIB_API Add(int lhs, int rhs);  


            MyMathLib.cpp

            1. #include "MyMathLib.h"   
            2.   
            3. int MYMATHLIB_API Add(int lhs, int rhs)  
            4. {  
            5.     return lhs + rhs;  
            6. }  


            除了創建.lib文件外,鏈接程序還要將一個輸出符號表嵌入產生的DLL文件。可以使用dumpbin程序察看dll的輸出節。

            1. >dumpbin -exports MyMathLib.dll  
            2. Microsoft (R) COFF/PE Dumper Version 10.00.30319.01  
            3. Copyright (C) Microsoft Corporation. All rights reserved.  
            4.   
            5.   
            6. Dump of file MyMathLib.dll  
            7.   
            8. File Type: DLL  
            9.   
            10. Section contains the following exports for MyMathLib.dll  
            11.   
            12. 00000000 characteristics  
            13. 4E258F37 time date stamp Tue Jul 19 22:05:43 2011  
            14. 0.00 version  
            15. 1 ordinal base  
            16. 1 number of functions  
            17. 1 number of names  
            18.   
            19. ordinal hint RVA name  
            20.   
            21. 1 0 0001106E ?Add@@YAHHH@Z = @ILT+105(?Add@@YAHHH@Z)  
            22.   
            23. Summary  
            24.   
            25. 1000 .data  
            26. 1000 .idata  
            27. 2000 .rdata  
            28. 1000 .reloc  
            29. 1000 .rsrc  
            30. 4000 .text  
            31. 10000 .textbss  


            2)創建可執行模塊

            可執行模塊引用DLL的頭文件,使用__declspec(dllimport)符號進行定義。當編器看到修改變量,函數或類的__declspec(dllimport)時,它知道這個符號是從某個DLL模
            塊輸入的。創建產生的可執行模塊的鏈接程序必須確定哪些DLL包含代碼引用的所有輸入符號。因此你必須將DLL的.lib文件傳遞給鏈接程序。

            實際上,當輸入一個符號時,不必使用關鍵字__declspec(dllimport),只要使用標準的C關鍵字extern即可。但是如果編譯器預先知道你引用的符號將從一個DLL的.lib文件輸入,那么編譯器就能夠生成運行效率稍高的代碼。因此建議你盡量將__declspec(dllimport)關鍵字用于輸入函數和符號。

            MyEXE.cpp

            1. #include <iostream>   
            2. #include "MyMathLib.h"   
            3.   
            4. #pragma comment(lib, "MyMathLib.lib")    
            5.   
            6. int _tmain(int argc, _TCHAR* argv[])  
            7. {  
            8.     int ret = Add(1, 2);  
            9.     std::cout << ret << std::endl;  
            10.     return 0;  
            11. }  


            當鏈接程序進行輸入符號的轉換時,它就將一個稱為輸入節的特殊的節嵌入產生的可執行模塊。輸入節列出了該模塊需要的DLL模塊以及由每個DLL模塊引用的符號。
            可以使用dumpbin程序察看模塊的輸入節。

            1. Dump of file MyEXE.exe  
            2.   
            3. File Type: EXECUTABLE IMAGE  
            4.   
            5.   Section contains the following imports:  
            6.   
            7.     MSVCP100D.dll  
            8.                 ......  
            9.     MyMathLib.dll  
            10.                 4183BC Import Address Table  
            11.                 4181F8 Import Name Table  
            12.                      0 time date stamp  
            13.                      0 Index of first forwarder reference  
            14.   
            15.                     0 ?Add@@YAHHH@Z  
            16.   
            17.     MSVCR100D.dll  
            18.                 ......  
            19.     KERNEL32.dll  
            20.                 ......  


            3)調用約定

            __stdcall
            Pascal方式清理C方式壓棧,通常用于Win32 Api中,.參數從右向左壓入堆棧,.函數被調用者自己在退出時清空堆棧。

            __cdecl
            C調用約定The C default calling convention)按從右至左的順序壓參數入棧,由調用者把參數彈出棧。對于傳送參數的內存棧是由調用者來維護的(正因為如此,實現可變參數vararg的函數(如printf)只能使用該調用約定)。它是C和C++程序的缺省調用方式。每一個調用它的函數都包含清空堆棧的代碼,所以產生的可執行文件大小會比調用__stdcall函數的大。

            C編譯時函數名修飾約定規則:
            __stdcall調用約定在輸出函數名前加上一個下劃線前綴,后面加上一個“@”符號和其參數的字節數,格式為_functionname@number。
            __cdecl調用約定僅在輸出函數名前加上一個下劃線前綴,格式為_functionname。

            C++編譯時函數名修飾約定規則:
            __stdcall調用約定:
              1、以“?”標識函數名的開始,后跟函數名;
              2、函數名后面以“@@YG”標識參數表的開始,后跟參數表;
              3、參數表以代號表示:
              X--void ,D--char,E--unsigned char,F--short,H--int,I--unsigned int,J--long,K--unsigned long,M--float,N--double,_N--bool,....
              PA--表示指針,后面的代號表明指針類型,如果相同類型的指針連續出現,以“0”代替,一個“0”代表一次重復;
              4、參數表的第一項為該函數的返回值類型,其后依次為參數的數據類型,指針標識在其所指數據類型前;
              5、參數表后以“@Z”標識整個名字的結束,如果該函數無參數,則以“Z”標識結束。
              其格式為“?functionname@@YG*****@Z”或“?functionname@@YG*XZ”,
            __cdecl調用約定:規則同上面的_stdcall調用約定,只是參數表的開始標識由上面的“@@YG”變為“@@YA”。

            例如int Add(int lhs, int rhs) =〉 ?Add@@YAHHH@Z

             

            可以使用extern "C" 防止VC編譯器修改函數名字。

            1. #ifdef  __cplusplus   
            2. extern "C" {  
            3. #endif   
            4. int MYMATHLIB_API Add(int lhs, int rhs);  
            5. #ifdef  __cplusplus   
            6. }  
            7. #endif  

            重新生成MyMathLib.dll后,使用dumpbin察看輸出節:

            1. ordinal hint RVA      name  
            2.   
            3.       1    0 000110AF Add = @ILT+170(_Add)  

             

            如果加上__stdcall修飾符,

            1. #ifdef MYMATHLIB_EXPORTS   
            2. #define MYMATHLIB_API  __declspec(dllexport) __stdcall   
            3. #else   
            4. #define MYMATHLIB_API  __declspec(dllimport) __stdcall   
            5. #endif   
            6.   
            7.   
            8. #ifdef  __cplusplus   
            9. extern "C" {  
            10. #endif   
            11. int MYMATHLIB_API Add(int lhs, int rhs);  
            12. #ifdef  __cplusplus   
            13. }  
            14. #endif  

            重新生成MyMathLib.dll后,使用dumpbin察看輸出節:

            1. ordinal hint RVA      name  
            2.   
            3.       1    0 00011087 _Add@8 = @ILT+130(_Add@8)  

             

            一般使用extern "C" 實現C++與C及其它語言的混合編程。
            如果在C++中引用C語言中的函數和變量,在包含C語言頭文件時,或者C++調用一個C語言編寫的.DLL時,當包括.DLL的頭文件或聲明接口函數時,應加extern "C" { }。
            在C中引用C++語言中的函數和變量時,比如回調函數,C++的頭文件需添加extern "C"。

            4).def文件

            模塊定義 (.def) 文件是包含一個或多個描述 DLL 各種屬性的 Module 語句的文本文件。如果不使用 __declspec(dllexport) 關鍵字導出 DLL 的函數,則 DLL 需要 .def 文件。
            .def 文件必須至少包含下列模塊定義語句:
            文件中的第一個語句必須是 LIBRARY 語句。此語句將 .def 文件標識為屬于 DLL。LIBRARY 語句的后面是 DLL 的名稱。鏈接器將此名稱放到 DLL 的導入庫中。
            EXPORTS 語句列出名稱,可能的話還會列出 DLL 導出函數的序號值。通過在函數名的后面加上 @ 符和一個數字,給函數分配序號值。

            MyMathLib.h

            1. int Add(int lhs, int rhs);  

            MyMathLib.cpp

            1. #include "MyMathLib.h"   
            2.   
            3. int Add(int lhs, int rhs)  
            4. {  
            5.     return lhs + rhs;  
            6. }  

            MyMathLib.def

            1. LIBRARY MyMathLib  
            2. EXPORTS  
            3.     Add     @100  

            重新生成MyMathLib.dll后,使用dumpbin察看輸出節:

            1. ordinal hint RVA      name  
            2.   
            3.     100    0 0001106E Add = @ILT+105(?Add@@YAHHH@Z)  

            當生成 DLL 時,鏈接器使用 .def 文件創建導出 (.exp) 文件和導入庫 (.lib) 文件。然后,鏈接器使用導出文件生成 DLL 文件。隱式鏈接到 DLL 的可執行文件在生成時鏈接到導入庫。可以使用dumpbin程序察看可執行文件的輸入節。可以看到現在是按序號進行連接了。

            1. MyMathLib.dll  
            2.             4183BC Import Address Table  
            3.             4181F8 Import Name Table  
            4.                  0 time date stamp  
            5.                  0 Index of first forwarder reference  
            6.   
            7.                   Ordinal   100  


            http://blog.csdn.net/fw0124/article/details/6618405

            posted on 2011-09-26 19:06 厚積薄發 閱讀(253) 評論(0)  編輯 收藏 引用 所屬分類: Windows編程

            導航

            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            統計

            常用鏈接

            留言簿

            隨筆分類

            文章分類

            文章檔案

            搜索

            最新評論

            婷婷久久香蕉五月综合加勒比| 18禁黄久久久AAA片| 亚洲国产成人久久笫一页| 精品久久久久久久无码 | 亚洲精品无码专区久久久| 久久婷婷五月综合97色直播| 97精品伊人久久大香线蕉app| 国产69精品久久久久久人妻精品| 久久免费视频一区| 精品久久人人爽天天玩人人妻| 久久99精品国产99久久6男男| 久久久久久久久无码精品亚洲日韩| 久久频这里精品99香蕉久| 亚洲精品无码久久久| 人妻无码久久精品| 亚洲国产精品成人久久蜜臀| 香蕉久久夜色精品国产2020| 久久久亚洲裙底偷窥综合| 亚洲女久久久噜噜噜熟女| 久久久久亚洲av无码专区喷水 | 国产一区二区精品久久岳| 天天爽天天爽天天片a久久网| 91久久成人免费| 久久国产精品偷99| 久久久久国产精品人妻| 伊人久久精品无码av一区| 久久精品二区| 久久久久久精品免费免费自慰| 性做久久久久久久| 天天综合久久久网| 亚洲日韩欧美一区久久久久我 | 国产精品无码久久综合| 日本精品久久久久中文字幕8| 国产激情久久久久影院老熟女免费 | 亚洲国产日韩欧美综合久久| 亚洲精品tv久久久久| 大香伊人久久精品一区二区| 久久国产精品一国产精品金尊 | 国产精品久久久久乳精品爆| 久久中文字幕精品| 久久免费线看线看|