lib文件和dll文件

[TOC]

一. 簡介

1.1 C++兩種庫文件

  1. lib包含了函數(shù)所在的dll文件和文件中函數(shù)位置的信息(入口)速蕊,代碼由運行時加載在進程空間中的dll提供亡哄,稱為動態(tài)鏈接庫dynamic link library。(這種方式更靈活谅阿,寫的程序體積小资柔,但是需要.exe和dll同時發(fā)布)
  2. lib包含函數(shù)代碼本身,在編譯時直接將代碼加入程序當(dāng)中缩抡,稱為靜態(tài)鏈接庫static link library。(這種方式不是很靈活包颁,因為lib被編譯到.exe中瞻想,寫出的程序體積大,但是只需要發(fā)布exe即可娩嚼,不需要dll文件)

1.2 C++兩種鏈接方式

  1. 動態(tài)鏈接使用動態(tài)鏈接庫蘑险,允許可執(zhí)行模塊(.dll文件或.exe文件)僅包含在運行時定位 dll 函數(shù)的可執(zhí)行代碼所需的信息。
  2. 靜態(tài)鏈接使用靜態(tài)鏈接庫岳悟,鏈接器從靜態(tài)鏈接庫 lib 獲取所有被引用函數(shù)漠其,并將庫同代碼一起放到可執(zhí)行文件中。

1.3 lib與dll的區(qū)別

1. 功能區(qū)別

  • lib是編譯時用到的竿音,dll是運行時用到的。如果要完成源代碼的編譯拴驮,只需要lib春瞬;如果要使動態(tài)鏈接的程序運行起來,只需要dll套啤。
  • 如果有dll文件宽气,那么lib一般是一些索引信息,記錄了dll中函數(shù)的入口和位置潜沦,dll中是函數(shù)的具體內(nèi)容萄涯;如果只有l(wèi)ib文件,那么這個lib文件是靜態(tài)編譯出來的唆鸡,索引和實現(xiàn)都在其中涝影。使用靜態(tài)編譯的lib文件,在運行程序時不需要再掛動態(tài)庫争占,缺點是導(dǎo)致應(yīng)用程序比較大燃逻,而且失去了動態(tài)庫的靈活性,發(fā)布新版本時要發(fā)布新的應(yīng)用程序才行臂痕。
  • 動態(tài)鏈接的情況下伯襟,有兩個文件:一個是LIB文件,一個是DLL文件握童。LIB包含被DLL導(dǎo)出的函數(shù)名稱和位置姆怪,DLL包含實際的函數(shù)和數(shù)據(jù),應(yīng)用程序使用LIB文件鏈接到DLL文件。在應(yīng)用程序的可執(zhí)行文件中稽揭,存放的不是被調(diào)用的函數(shù)代碼俺附,而是DLL中相應(yīng)函數(shù)代碼的地址,從而節(jié)省了內(nèi)存資源淀衣。DLL和LIB文件必須隨應(yīng)用程序一起發(fā)行昙读,否則應(yīng)用程序會產(chǎn)生錯誤。如果不想用lib文件或者沒有l(wèi)ib文件膨桥,可以用WIN32 API函數(shù)LoadLibrary蛮浑、GetProcAddress裝載。

2. 文件數(shù)量的區(qū)別

  1. (靜態(tài)連接)使用lib需注意兩個文件:
  • .h頭文件只嚣,包含lib中說明輸出的類或符號原型或數(shù)據(jù)結(jié)構(gòu)沮稚。應(yīng)用程序調(diào)用lib時,需要將該文件包含入應(yīng)用程序的源文件中册舞。
  • .LIB文件蕴掏,略。
  1. (動態(tài)連接)使用dll需注意三個文件:
  • .h頭文件调鲸,包含dll中說明輸出的類或符號原型或數(shù)據(jù)結(jié)構(gòu)的.h文件盛杰。應(yīng)用程序調(diào)用dll時,需要將該文件包含入應(yīng)用程序的源文件中藐石。
  • .LIB文件即供,是dll在編譯、鏈接成功之后生成的文件于微,作用是當(dāng)其他應(yīng)用程序調(diào)用dll時逗嫡,需要將該文件引入應(yīng)用程序,否則產(chǎn)生錯誤株依。如果不想用lib文件或者沒有l(wèi)ib文件驱证,可以用WIN32API函數(shù)LoadLibrary、GetProcAddress裝載恋腕。
  • .dll文件抹锄,真正的可執(zhí)行文件,開發(fā)成功后的應(yīng)用程序在發(fā)布時荠藤,只需要有.exe文件和.dll文件祈远,并不需要.lib文件和.h頭文件。

二. lib文件

2.1 生成工具

操作系統(tǒng): Win7

開發(fā)軟件: VS2010

2.2 生成步驟

  1. 建立win32控制臺工程MyLib(或者win32項目中下的靜態(tài)庫), 添加mySub.h文件以及mySub.cpp文件商源。

  2. 編寫mySub.h文件代碼

    #ifndef _MYSUB_H               // 這里的#ifndef可以避免頭文件重復(fù)包含
    #define _MYSUB_H  
    void mySub(int a,int b);       // 這一行代碼不能夠?qū)懺谏弦恍谐捣荩荒芰砥鹨恍袑?#endif
    
  3. 編寫mySub.cpp文件代碼

      #include "mySub.h"                   //包含頭文件
      #include <iostream>                  
                                       
      void mySub(int a,int b)              //自定義的函數(shù) 
      {
         std::cout<<(a-b)<<std::endl;
      }
    
  4. 由于在工程中,沒有main()函數(shù)牡彻,所以編譯可能會出錯扫沼。這時出爹,點擊工程,并選擇工程屬性缎除,出現(xiàn)下圖严就,選擇靜態(tài)鏈接庫即可。

    012302.png
  1. 這時候再按快捷鍵 F7器罐,build solution即可產(chǎn)生lib文件梢为。在Debug中只生成.lib文件。

2.3 lib文件的使用

  1. 新建一個.cpp文件myLibTest.cpp(用于測試)

    #include <iostream>
    #include "mySub.h"                       // 引用頭文件
    using namespace std;
    
    #pragma comment(lib,"MyLib.lib")         // 導(dǎo)入上一步生成的lib文件
    
    int main()
    {
      mySub(5,4);                            // 調(diào)用lib中的自定義函數(shù)mySub()
    
      return 0;
    }
    
  2. 點擊工程轰坊,并選擇工程屬性铸董,出現(xiàn)下圖,將附加庫目錄新增包含剛才生成.lib的目錄肴沫。

    012303.png
  1. 將工程項目屬性中的配置類型改回至原來默認(rèn)的應(yīng)用程序(.exe),并執(zhí)行myLibTest.cpp粟害。

三. dll文件

3.1 生成.dll文件

  1. 新建win32項目,項目名稱為SubDLL颤芬,解決方案名稱為DLLTest悲幅,下一步。

  2. 選擇應(yīng)用程序類型為DLL站蝠,將附加選項的“導(dǎo)出符號”勾選上汰具,完成。

  3. 修改SubDLL.h中的內(nèi)容(將原來代碼中菱魔,除預(yù)處理部分的代碼外全部刪除)郁副,并在后面新增你要實現(xiàn)的函數(shù)聲明(見代碼第21行)。注意:項目名為SubDLL豌习,但此時生成的名字為 SUBDLL。

    #ifdef SUBDLL_EXPORTS
    #define SUBDLL_API __declspec(dllexport)
    #else
    #define SUBDLL_API __declspec(dllimport)
    #endif
    
    /*
    // 此類是從 SubDLL.dll 導(dǎo)出的
    class SUBDLL_API CSubDLL {
    public:
     CSubDLL(void);
     // TODO: 在此添加您的方法拔疚。
    };
    
    extern SUBDLL_API int nSubDLL;
    
    SUBDLL_API int fnSubDLL(void);
    */
    
    //這邊是新增的內(nèi)容
    SUBDLL_API void mySub(); 
    
    
  4. 修改SubDLL.cpp中的內(nèi)容(將原來代碼中肥隆,除頭文件引入部分的代碼外全部刪除),并在后面新增你要實現(xiàn)的函數(shù)聲明(見代碼第26行)稚失。

    // SubDLL.cpp : 定義 DLL 應(yīng)用程序的導(dǎo)出函數(shù)栋艳。
    //
    
    #include "stdafx.h"
    #include "SubDLL.h"
    
    #include<stdio.h>
    /*
    // 這是導(dǎo)出變量的一個示例
    SUBDLL_API int nSubDLL=0;
    
    // 這是導(dǎo)出函數(shù)的一個示例。
    SUBDLL_API int fnSubDLL(void)
    {
     return 42;
    }
    
    // 這是已導(dǎo)出類的構(gòu)造函數(shù)句各。
    // 有關(guān)類定義的信息吸占,請參閱 SubDLL.h
    CSubDLL::CSubDLL()
    {
     return;
    }
    */
    //這邊為SUM()的內(nèi)容,很簡易
    SUBDLL_API void mySub(int a,int b)
    {
     printf("the result is %d",a-b);
    }
    
    
  5. 點擊“項目”凿宾,選擇“屬性”矾屯,進行如下圖的配置(粗體字顯示部分)。

    012306.png
  1. 構(gòu)建項目(build)/生成解決方案初厚,在項目的debug目錄下面會生成很多的文件件蚕,其中包括有.dll和.lib。

3.2 dll文件的使用

3.2.1 顯示調(diào)用方式

  1. 在之前“解決方案”中新建項目(選中解決方案 -> 增加 -> 新建項目),這次選擇“win32控制臺應(yīng)用程序”排作,生成向?qū)е羞x擇“空項目”即可牵啦。取名為MyTest。

  2. 在新建項目的源文件下新建一個UseDLL.cpp文件妄痪,下面是其中的代碼哈雏。

    #include <iostream>
    #include <Windows.h>          //使用函數(shù)和某些特殊變量
    
    using namespace std;
    typedef void (*FUN)(int,int); //定義一個函數(shù)指針,確定調(diào)用函數(shù)的形參
    
    int main()
    {
     const char* dllname = "SUBDLL.dll"; // 加載.dll
     const char* funname = "mySub";      //SUMDLL.cpp中函數(shù)名稱
    
     HMODULE hDLL = LoadLibrary(dllname); //不要問衫生,跟著做
    
     if (hDLL != NULL)
     {
         FUN fp = FUN(GetProcAddress(hDLL,funname)); //繼續(xù)做裳瘪,不要問
         if(fp != NULL)
            {
              fp(5,4);
            }
         else 
            {
              cout << "Can not Find: " << funname << endl;
            }    
         FreeLibrary(hDLL);
     }
     else 
         cout << "Can not find: " << dllname;
      
     return 0;
    }
    
    
  3. 點擊解決方案名,選擇設(shè)置啟動項目 -> 通用屬性 -> 啟動項目 -> 單啟動項目(選中UseDLL)障簿。

  4. 運行項目盹愚,出現(xiàn)了錯誤:Can not find:mySub。造成這種錯誤的原因正是導(dǎo)出函數(shù)的修飾名稱站故。在dll二進制文件中皆怕,經(jīng)過編譯器的“加工”,實際上有了不同的名稱西篓。這也是函數(shù)重載機制得以實現(xiàn)的一個技術(shù)支持愈腾。怎么辦呢?我們可以通過vs2010附帶工具dumpbin岂津,找到加工以后的名稱虱黄。詳見dumpbin工具的使用

    • 在C:\Program Files(x86)\Microsoft Visual Studio 10.0\VC\bin目錄下,按住shift鍵吮成,鼠標(biāo)右鍵在空白處單擊橱乱,選擇在此處打開命令窗口
    • 輸入命令: dumpbin /export 文件全名
    • 將“加工”后的真是函數(shù)名復(fù)制后,粘貼粱甫。賦值給UseDLL.cpp文件中的變量funname泳叠。
    • 經(jīng)過上一步后,重新執(zhí)行UseDLL.cpp茶宵,成功運行危纫。詳見VS2010 C++ 調(diào)用 DLL (C++編寫)
  5. 為了能夠使原來的UseDLL.cpp(上面第2步所示代碼)成功運行,可以進行下列操作:

    • 生成DLL文件的SubDLL項目的源文件中新建模塊定義文件createDLL.def乌庶,其中的代碼如下:

      LIBRARY createDLL  
      EXPORTS  
      mySub = ?mySub@@YAXHH@Z          //?mySub@@YAXHH@Z 即為dumpbin工具找到的真實名种蝶。
      
    • 修改SubDLL.h中的代碼(去掉這些不太規(guī)范的修飾名稱),修改之后重新編譯生成CreateDLL.dll瞒大。

      #ifdef SUBDLL_EXPORTS
      #define SUBDLL_API        //去掉了原來的 __declspec(dllexport) 
      #else              //或改為 #define SUBDLL_API  extern "C" __declspec(dllexport)
      #define  SUBDLL_API           //同上  
      #endif
      
      
  6. 重新運行UseDLL.cpp程序螃征,成功執(zhí)行。

3.2.2 隱式調(diào)用方式

  1. 在之前“解決方案”中新建項目(選中解決方案 -> 增加 -> 新建項目)透敌,這次選擇“win32控制臺應(yīng)用程序”会傲,生成向?qū)е羞x擇“空項目”即可锅棕。取名為MyTest。

  2. 在新建項目的源文件下新建一個UseDLL.cpp文件淌山,下面是其中的代碼裸燎。

    #include <iostream>
    
    extern void mySub(int,int);
    
    int main()
    {
     mySub(5,4);
     return 0;
    }
    
  3. 右鍵工程–>Linker–>General–>Additional Library Directories(附加庫目錄) –>找到那個SubDLL.lib所在的目錄

  4. 右鍵UseDLL工程–>Linker->input寫下lib的名稱。如SubDLL.lib和你DEBUG文件下的對應(yīng)(這步?jīng)]有也可以泼疑,因為會在上一步的路徑下尋找)德绿。

  5. 點擊解決方案名,選擇設(shè)置啟動項目 -> 通用屬性 -> 啟動項目 -> 單啟動項目(選中UseDLL)

  6. 運行UseDLL.cpp程序退渗,成功執(zhí)行移稳。

參考資料

四. 小結(jié)

4.1 程序中的問題

  1. error C2664: “LoadLibraryW”: 不能將參數(shù) 1 從“const char [10]”轉(zhuǎn)換為“LPCWSTR”與指向的類型無關(guān);轉(zhuǎn)換要求 reinterpret_cast会油、C 樣式轉(zhuǎn)換或函數(shù)樣式轉(zhuǎn)換
    解決方法:

    選中項目个粱,然后點擊屬性——>配置屬性——>常規(guī)——>項目默認(rèn)值——>字符集,選為“使用多字節(jié)字符集"

    012304.png
  1. fatal error LNK1104: 無法打開文件:×××.lib的解決辦法
    一般情況是因為沒有導(dǎo)入相應(yīng)的.lib文件翻翩,或者是導(dǎo)入的路徑有誤都许。給項目添加庫文件路徑。

    在VS中右擊項目點屬性:

    配置屬性-->鏈接器-->常規(guī)-->附加目錄 嫂冻。在里面填上庫文件所在的路徑即可胶征。

  2. fatal error LNK1104: 無法打開文件“x x x.def”
    如果不想使用xxx.def文件,可以在項目-屬性-配置屬性-鏈接器-輸入 選項中桨仿,將右側(cè)的模塊定義文件刪掉睛低,這樣就不會提示了。

4.2 vs的常用操作

  1. 添加頭文件:

    配置屬性-->C/C++-->常規(guī)-->附加包含目錄 加上頭文件存放的目錄服傍。

  2. 添加lib文件:

    • 配置屬性-->鏈接器-->輸入-->附加依賴項加入庫名(×××.lib)钱雷;或者是在cpp源文件中用#pragma comment(lib,"×××.lib")來代替。
    • 將xxx.lib拷入工程所在目錄吹零,或者執(zhí)行文件生成的目錄罩抗,或者系統(tǒng)Lib目錄中(如果lib文件是自己生成的,可以跳過這一步)瘪校。
    • 給項目添加庫文件路徑:
      在VS中右擊項目點屬性。配置屬性-->鏈接器-->常規(guī)-->附加目錄 名段。在里面填上庫文件所在的路徑即可阱扬。

4.3 windows小常識

  1. 在當(dāng)前目錄下運行命令:shift鍵 + 鼠標(biāo)右鍵

  2. 首先將命令窗體屬性中的快速編輯模式選中打勾,這樣就可以一復(fù)制粘貼了伸辟。復(fù)制dos窗體中的內(nèi)容:右鍵->標(biāo)記->選擇復(fù)制內(nèi)容->回車鍵或者鼠標(biāo)右擊麻惶,粘貼的時候:鼠標(biāo)右鍵粘貼。
    dos中不能使用快捷鍵信夫。

    ?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末窃蹋,一起剝皮案震驚了整個濱河市卡啰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌警没,老刑警劉巖匈辱,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異杀迹,居然都是意外死亡亡脸,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進店門树酪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來浅碾,“玉大人,你說我怎么就攤上這事续语〈剐唬” “怎么了?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵疮茄,是天一觀的道長滥朱。 經(jīng)常有香客問我,道長娃豹,這世上最難降的妖魔是什么焚虱? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮懂版,結(jié)果婚禮上鹃栽,老公的妹妹穿的比我還像新娘。我一直安慰自己躯畴,他們只是感情好民鼓,可當(dāng)我...
    茶點故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蓬抄,像睡著了一般丰嘉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嚷缭,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天饮亏,我揣著相機與錄音,去河邊找鬼阅爽。 笑死路幸,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的付翁。 我是一名探鬼主播简肴,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼百侧!你這毒婦竟也來了砰识?” 一聲冷哼從身側(cè)響起能扒,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎辫狼,沒想到半個月后初斑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡予借,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年越平,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片灵迫。...
    茶點故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡秦叛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出瀑粥,到底是詐尸還是另有隱情挣跋,我是刑警寧澤,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布狞换,位于F島的核電站避咆,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏修噪。R本人自食惡果不足惜查库,卻給世界環(huán)境...
    茶點故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望黄琼。 院中可真熱鬧樊销,春花似錦、人聲如沸脏款。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽撤师。三九已至剂府,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間剃盾,已是汗流浹背腺占。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留痒谴,地道東北人衰伯。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像闰歪,于是被迫代替她去往敵國和親嚎研。 傳聞我的和親對象是個殘疾皇子蓖墅,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,697評論 2 351

推薦閱讀更多精彩內(nèi)容